linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] m88ds3103: Add support for Montage 3103b DVB-S demod
@ 2020-02-01 21:48 Brad Love
  2020-02-01 21:48 ` [PATCH 1/3] m88ds3103: Add support for ds3103b demod Brad Love
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Brad Love @ 2020-02-01 21:48 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love

The following series implements the necessary changes to allow the
Montage m88ds3103b satellite demodulator to work.

The 3103b demod identifies as an m88rs6000, but has significant operating
differences. The 3103b demod has a dynamic clocking chip that must be set
up. There are also register settings that only apply to the 3103b.
There is also a new firmware that must be used.

The driver was developed by reverse engineering the differences between
i2c traffic using an instrumented downstream GPLv2 vendor driver and
the upstream m88ds3103 driver. The mclk functions are from the downstream
driver.

The demodulator is used by Hauppauge 461e Rev2 B8H9.
The demodulator is also used by Terratec S2 USB Box Rev 4.

Bridge support for detection of the new demodulator has been added to
handle both devices. Both models are confirmed working.




Brad Love (3):
  m88ds3103: Add support for ds3103b demod
  em28xx: Enable Hauppauge 461e rev2
  dw2102: probe for demodulator i2c address

 drivers/media/dvb-frontends/m88ds3103.c      | 466 ++++++++++++++++++-
 drivers/media/dvb-frontends/m88ds3103_priv.h |  14 +-
 drivers/media/usb/dvb-usb/dw2102.c           |  45 +-
 drivers/media/usb/em28xx/em28xx-cards.c      |  18 +
 drivers/media/usb/em28xx/em28xx-dvb.c        |  60 +++
 drivers/media/usb/em28xx/em28xx.h            |   1 +
 6 files changed, 589 insertions(+), 15 deletions(-)

-- 
2.23.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] m88ds3103: Add support for ds3103b demod
  2020-02-01 21:48 [PATCH 0/3] m88ds3103: Add support for Montage 3103b DVB-S demod Brad Love
@ 2020-02-01 21:48 ` Brad Love
  2020-02-03 10:03   ` kbuild test robot
  2020-02-03 11:09   ` kbuild test robot
  2020-02-01 21:48 ` [PATCH 2/3] em28xx: Enable Hauppauge 461e rev2 Brad Love
  2020-02-01 21:48 ` [PATCH 3/3] dw2102: probe for demodulator i2c address Brad Love
  2 siblings, 2 replies; 6+ messages in thread
From: Brad Love @ 2020-02-01 21:48 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love

The ds3103b demodulator identifies as an m88rs600, but requires different
clock settings and firmware, along with differences in register settings.

Changes were reverse engineered using an instrumented downstream GPLv2
driver to compare i2c traffic and clocking. The mclk functions are from
the downstream GPLv2 driver.

Signed-off-by: Brad Love <brad@nextdimension.cc>
---
 drivers/media/dvb-frontends/m88ds3103.c      | 466 ++++++++++++++++++-
 drivers/media/dvb-frontends/m88ds3103_priv.h |  14 +-
 2 files changed, 467 insertions(+), 13 deletions(-)

diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index c96f05ff5f2f..baf21b999ccc 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -64,6 +64,92 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
 	return ret;
 }
 
+/*
+ * m88ds3103b demod has an internal device related to clocking. First the i2c
+ * gate must be opened, for one transaction, then writes will be allowed.
+ */
+static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data)
+{
+	struct i2c_client *client = dev->client;
+	u8 buf[] = {reg, data};
+	u8 val;
+	int ret;
+	struct i2c_msg msg = {
+		.addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2
+	};
+
+	m88ds3103_update_bits(dev, 0x11, 0x01, 0x00);
+
+	val = 0x11;
+	ret = regmap_write(dev->regmap, 0x03, val);
+	if (ret)
+		dev_dbg(&client->dev, "fail=%d\n", ret);
+
+	ret = i2c_transfer(dev->dt_client->adapter, &msg, 1);
+	if (ret != 1) {
+		dev_err(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n",
+			dev->dt_addr, ret, reg, data);
+
+		m88ds3103_update_bits(dev, 0x11, 0x01, 0x01);
+		return -EREMOTEIO;
+	}
+	m88ds3103_update_bits(dev, 0x11, 0x01, 0x01);
+
+	dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n",
+		dev->dt_addr, reg, data);
+
+	return 0;
+}
+
+/*
+ * m88ds3103b demod has an internal device related to clocking. First the i2c
+ * gate must be opened, for two transactions, then reads will be allowed.
+ */
+static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg)
+{
+	struct i2c_client *client = dev->client;
+	int ret;
+	u8 val;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = dev->dt_addr,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		},
+		{
+			.addr = dev->dt_addr,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+
+	m88ds3103_update_bits(dev, 0x11, 0x01, 0x00);
+
+	val = 0x12;
+	ret = regmap_write(dev->regmap, 0x03, val);
+	if (ret)
+		dev_dbg(&client->dev, "fail=%d\n", ret);
+
+	ret = i2c_transfer(dev->dt_client->adapter, msg, 2);
+	if (ret != 2) {
+		dev_err(&client->dev, "0x%02x (ret=%d, reg=0x%02x)\n",
+			dev->dt_addr, ret, reg);
+
+		m88ds3103_update_bits(dev, 0x11, 0x01, 0x01);
+		return -EREMOTEIO;
+	}
+	m88ds3103_update_bits(dev, 0x11, 0x01, 0x01);
+
+	dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n",
+		dev->dt_addr, reg, b1[0]);
+
+	return b1[0];
+}
+
 /*
  * Get the demodulator AGC PWM voltage setting supplied to the tuner.
  */
@@ -288,6 +374,253 @@ static int m88ds3103_read_status(struct dvb_frontend *fe,
 	return ret;
 }
 
+static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev)
+{
+	struct i2c_client *client = dev->client;
+	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
+	u32 adc_Freq_MHz[3] = {96, 93, 99};
+	u8  reg16_list[3] = {96, 92, 100}, reg16, reg15;
+	u32 offset_MHz[3];
+	u32 max_offset = 0;
+	u32 old_setting = dev->mclk;
+	u32 tuner_freq_MHz = c->frequency / 1000;
+	u8 i;
+	char big_symbol = 0;
+
+	big_symbol = (c->symbol_rate > 45010000) ? 1 : 0;
+
+	if (big_symbol) {
+		reg16 = 115;
+	} else {
+		reg16 = 96;
+
+		/* TODO: IS THIS NECESSARY ? */
+		for (i = 0; i < 3; i++) {
+			offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i];
+
+			if (offset_MHz[i] > (adc_Freq_MHz[i] / 2))
+				offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i];
+
+			if (offset_MHz[i] > max_offset) {
+				max_offset = offset_MHz[i];
+				reg16 = reg16_list[i];
+				dev->mclk = adc_Freq_MHz[i] * 1000 * 1000;
+
+				if (big_symbol)
+					dev->mclk /= 2;
+
+				dev_dbg(&client->dev, "modifying mclk %u -> %u\n",
+					old_setting, dev->mclk);
+			}
+		}
+	}
+
+	if (dev->mclk == 93000000)
+		regmap_write(dev->regmap, 0xA0, 0x42);
+	else if (dev->mclk == 96000000)
+		regmap_write(dev->regmap, 0xA0, 0x44);
+	else if (dev->mclk == 99000000)
+		regmap_write(dev->regmap, 0xA0, 0x46);
+	else if (dev->mclk == 110250000)
+		regmap_write(dev->regmap, 0xA0, 0x4E);
+	else
+		regmap_write(dev->regmap, 0xA0, 0x44);
+
+	reg15 = m88ds3103b_dt_read(dev, 0x15);
+
+	m88ds3103b_dt_write(dev, 0x05, 0x40);
+	m88ds3103b_dt_write(dev, 0x11, 0x08);
+
+	if (big_symbol)
+		reg15 |= 0x02;
+	else
+		reg15 &= ~0x02;
+
+	m88ds3103b_dt_write(dev, 0x15, reg15);
+	m88ds3103b_dt_write(dev, 0x16, reg16);
+
+	usleep_range(5000, 5500);
+
+	m88ds3103b_dt_write(dev, 0x05, 0x00);
+	m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A));
+
+	usleep_range(5000, 5500);
+
+	return 0;
+}
+
+static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz)
+{
+	u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp;
+	u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0, pll_ldpc_mode;
+	u16 pll_div_fb, N;
+	u32 div;
+
+	reg15 = m88ds3103b_dt_read(dev, 0x15);
+	reg16 = m88ds3103b_dt_read(dev, 0x16);
+	reg1D = m88ds3103b_dt_read(dev, 0x1D);
+
+	if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) {
+		if (reg16 == 92)
+			tmp = 93;
+		else if (reg16 == 100)
+			tmp = 99;
+		else
+			tmp = 96;
+
+		mclk_khz *= tmp;
+		mclk_khz /= 96;
+	}
+
+	pll_ldpc_mode = (reg15 >> 1) & 0x01;
+
+	pll_div_fb = (reg15 & 0x01) << 8;
+	pll_div_fb += reg16;
+	pll_div_fb += 32;
+
+	div = 9000 * pll_div_fb * 4;
+	div /= mclk_khz;
+
+	if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) {
+		reg11 |= 0x02;
+
+		if (div <= 32) {
+			N = 2;
+
+			f0 = 0;
+			f1 = div / N;
+			f2 = div - f1;
+			f3 = 0;
+		} else if (div <= 34) {
+			N = 3;
+
+			f0 = div / N;
+			f1 = (div - f0) / (N - 1);
+			f2 = div - f0 - f1;
+			f3 = 0;
+		} else if (div <= 64) {
+			N = 4;
+
+			f0 = div / N;
+			f1 = (div - f0) / (N - 1);
+			f2 = (div - f0 - f1) / (N - 2);
+			f3 = div - f0 - f1 - f2;
+		} else {
+			N = 4;
+
+			f0 = 16;
+			f1 = 16;
+			f2 = 16;
+			f3 = 16;
+		}
+
+		if (f0 == 16)
+			f0 = 0;
+		else if ((f0 < 8) && (f0 != 0))
+			f0 = 8;
+
+		if (f1 == 16)
+			f1 = 0;
+		else if ((f1 < 8) && (f1 != 0))
+			f1 = 8;
+
+		if (f2 == 16)
+			f2 = 0;
+		else if ((f2 < 8) && (f2 != 0))
+			f2 = 8;
+
+		if (f3 == 16)
+			f3 = 0;
+		else if ((f3 < 8) && (f3 != 0))
+			f3 = 8;
+	} else {
+		reg11 &= ~0x02;
+
+		if (div <= 32) {
+			N = 2;
+
+			f0 = 0;
+			f1 = div / N;
+			f2 = div - f1;
+			f3 = 0;
+		} else if (div <= 48) {
+			N = 3;
+
+			f0 = div / N;
+			f1 = (div - f0) / (N - 1);
+			f2 = div - f0 - f1;
+			f3 = 0;
+		} else if (div <= 64) {
+			N = 4;
+
+			f0 = div / N;
+			f1 = (div - f0) / (N - 1);
+			f2 = (div - f0 - f1) / (N - 2);
+			f3 = div - f0 - f1 - f2;
+		} else {
+			N = 4;
+
+			f0 = 16;
+			f1 = 16;
+			f2 = 16;
+			f3 = 16;
+		}
+
+		if (f0 == 16)
+			f0 = 0;
+		else if ((f0 < 9) && (f0 != 0))
+			f0 = 9;
+
+		if (f1 == 16)
+			f1 = 0;
+		else if ((f1 < 9) && (f1 != 0))
+			f1 = 9;
+
+		if (f2 == 16)
+			f2 = 0;
+		else if ((f2 < 9) && (f2 != 0))
+			f2 = 9;
+
+		if (f3 == 16)
+			f3 = 0;
+		else if ((f3 < 9) && (f3 != 0))
+			f3 = 9;
+	}
+
+	sm = N - 1;
+
+	/* Write to registers */
+	//reg15 &= 0x01;
+	//reg15 |= (pll_div_fb >> 8) & 0x01;
+
+	//reg16 = pll_div_fb & 0xFF;
+
+	reg1D &= ~0x03;
+	reg1D |= sm;
+	reg1D |= 0x80;
+
+	reg1E = ((f3 << 4) + f2) & 0xFF;
+	reg1F = ((f1 << 4) + f0) & 0xFF;
+
+	m88ds3103b_dt_write(dev, 0x05, 0x40);
+	m88ds3103b_dt_write(dev, 0x11, 0x08);
+	m88ds3103b_dt_write(dev, 0x1D, reg1D);
+	m88ds3103b_dt_write(dev, 0x1E, reg1E);
+	m88ds3103b_dt_write(dev, 0x1F, reg1F);
+
+	m88ds3103b_dt_write(dev, 0x17, 0xc1);
+	m88ds3103b_dt_write(dev, 0x17, 0x81);
+
+	usleep_range(5000, 5500);
+
+	m88ds3103b_dt_write(dev, 0x05, 0x00);
+	m88ds3103b_dt_write(dev, 0x11, 0x0A);
+
+	usleep_range(5000, 5500);
+
+	return 0;
+}
+
 static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 {
 	struct m88ds3103_dev *dev = fe->demodulator_priv;
@@ -298,7 +631,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 	u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */
 	u8 buf[3];
 	u16 u16tmp;
-	u32 tuner_frequency_khz, target_mclk;
+	u32 tuner_frequency_khz, target_mclk, u32tmp;
 	s32 s32tmp;
 	static const struct reg_sequence reset_buf[] = {
 		{0x07, 0x80}, {0x07, 0x00}
@@ -321,6 +654,20 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 
 	/* Disable demod clock path */
 	if (dev->chip_id == M88RS6000_CHIP_ID) {
+		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+			ret = regmap_read(dev->regmap, 0xb2, &u32tmp);
+			if (ret)
+				goto err;
+			if (u32tmp == 0x01) {
+				ret = regmap_write(dev->regmap, 0x00, 0x00);
+				if (ret)
+					goto err;
+				ret = regmap_write(dev->regmap, 0xb2, 0x00);
+				if (ret)
+					goto err;
+			}
+		}
+
 		ret = regmap_write(dev->regmap, 0x06, 0xe0);
 		if (ret)
 			goto err;
@@ -346,7 +693,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 		tuner_frequency_khz = c->frequency;
 	}
 
-	/* select M88RS6000 demod main mclk and ts mclk from tuner die. */
+	/* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */
 	if (dev->chip_id == M88RS6000_CHIP_ID) {
 		if (c->symbol_rate > 45010000)
 			dev->mclk = 110250000;
@@ -358,6 +705,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 		else
 			target_mclk = 144000000;
 
+		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+			m88ds3103b_select_mclk(dev);
+			m88ds3103b_set_mclk(dev, target_mclk / 1000);
+		}
+
 		/* Enable demod clock path */
 		ret = regmap_write(dev->regmap, 0x06, 0x00);
 		if (ret)
@@ -469,12 +821,42 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 		ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
 		if (ret)
 			goto err;
+
+		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+			buf[0] = m88ds3103b_dt_read(dev, 0x15);
+			buf[1] = m88ds3103b_dt_read(dev, 0x16);
+
+			if (c->symbol_rate > 45010000) {
+				buf[0] &= ~0x03;
+				buf[0] |= 0x02;
+				buf[0] |= ((147 - 32) >> 8) & 0x01;
+				buf[1] = (147 - 32) & 0xFF;
+
+				dev->mclk = 110250 * 1000;
+			} else {
+				buf[0] &= ~0x03;
+				buf[0] |= ((128 - 32) >> 8) & 0x01;
+				buf[1] = (128 - 32) & 0xFF;
+
+				dev->mclk = 96000 * 1000;
+			}
+			m88ds3103b_dt_write(dev, 0x15, buf[0]);
+			m88ds3103b_dt_write(dev, 0x16, buf[1]);
+
+			regmap_read(dev->regmap, 0x30, &u32tmp);
+			u32tmp &= ~0x80;
+			regmap_write(dev->regmap, 0x30, u32tmp & 0xff);
+		}
+
 		ret = regmap_write(dev->regmap, 0xf1, 0x01);
 		if (ret)
 			goto err;
-		ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
-		if (ret)
-			goto err;
+
+		if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) {
+			ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
+			if (ret)
+				goto err;
+		}
 	}
 
 	switch (dev->cfg->ts_mode) {
@@ -488,6 +870,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 		break;
 	case M88DS3103_TS_PARALLEL:
 		u8tmp = 0x02;
+		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+			u8tmp = 0x01;
+			u8tmp1 = 0x01;
+		}
 		break;
 	case M88DS3103_TS_CI:
 		u8tmp = 0x03;
@@ -516,6 +902,12 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 		u8tmp1 = 0x3f;
 		u8tmp2 = 0x3f;
 		break;
+	case M88DS3103_TS_PARALLEL:
+		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+			ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1);
+			if (ret)
+				goto err;
+		}
 	default:
 		u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk);
 		u8tmp1 = u16tmp / 2 - 1;
@@ -543,6 +935,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 	else
 		u8tmp = 0x06;
 
+	if (dev->chiptype == M88DS3103_CHIPTYPE_3103B)
+		m88ds3103b_set_mclk(dev, target_mclk / 1000);
+
 	ret = regmap_write(dev->regmap, 0xc3, 0x08);
 	if (ret)
 		goto err;
@@ -578,6 +973,16 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
 	if (ret)
 		goto err;
 
+	if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+		/* enable/disable 192M LDPC clock */
+		ret = m88ds3103_update_bits(dev, 0x29, 0x10,
+					(c->delivery_system == SYS_DVBS) ? 0x10 : 0x0);
+		if (ret)
+			goto err;
+
+		ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08);
+	}
+
 	dev_dbg(&client->dev, "carrier offset=%d\n",
 		(tuner_frequency_khz - c->frequency));
 
@@ -642,7 +1047,7 @@ static int m88ds3103_init(struct dvb_frontend *fe)
 	if (utmp)
 		goto warm;
 
-	/* global reset, global diseqc reset, golbal fec reset */
+	/* global reset, global diseqc reset, global fec reset */
 	ret = regmap_write(dev->regmap, 0x07, 0xe0);
 	if (ret)
 		goto err;
@@ -652,12 +1057,15 @@ static int m88ds3103_init(struct dvb_frontend *fe)
 
 	/* cold state - try to download firmware */
 	dev_info(&client->dev, "found a '%s' in cold state\n",
-		 m88ds3103_ops.info.name);
+		 dev->fe.ops.info.name);
 
-	if (dev->chip_id == M88RS6000_CHIP_ID)
+	if (dev->chiptype == M88DS3103_CHIPTYPE_3103B)
+		name = M88DS3103B_FIRMWARE;
+	else if (dev->chip_id == M88RS6000_CHIP_ID)
 		name = M88RS6000_FIRMWARE;
 	else
 		name = M88DS3103_FIRMWARE;
+
 	/* request the firmware, this will block and timeout */
 	ret = request_firmware(&firmware, name, &client->dev);
 	if (ret) {
@@ -700,10 +1108,16 @@ static int m88ds3103_init(struct dvb_frontend *fe)
 	}
 
 	dev_info(&client->dev, "found a '%s' in warm state\n",
-		 m88ds3103_ops.info.name);
+		 dev->fe.ops.info.name);
 	dev_info(&client->dev, "firmware version: %X.%X\n",
 		 (utmp >> 4) & 0xf, (utmp >> 0 & 0xf));
 
+	if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+		m88ds3103b_dt_write(dev, 0x21, 0x92);
+		m88ds3103b_dt_write(dev, 0x15, 0x6C);
+		m88ds3103b_dt_write(dev, 0x17, 0xC1);
+		m88ds3103b_dt_write(dev, 0x17, 0x81);
+	}
 warm:
 	/* warm state */
 	dev->warm = true;
@@ -1393,6 +1807,8 @@ static int m88ds3103_probe(struct i2c_client *client,
 		goto err_kfree;
 
 	dev->chip_id = utmp >> 1;
+	dev->chiptype = (u8)id->driver_data;
+
 	dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id);
 
 	switch (dev->chip_id) {
@@ -1459,7 +1875,10 @@ static int m88ds3103_probe(struct i2c_client *client,
 
 	/* create dvb_frontend */
 	memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops));
-	if (dev->chip_id == M88RS6000_CHIP_ID)
+	if (dev->chiptype == M88DS3103_CHIPTYPE_3103B)
+		strscpy(dev->fe.ops.info.name, "Montage Technology M88DS3103B",
+			sizeof(dev->fe.ops.info.name));
+	else if (dev->chip_id == M88RS6000_CHIP_ID)
 		strscpy(dev->fe.ops.info.name, "Montage Technology M88RS6000",
 			sizeof(dev->fe.ops.info.name));
 	if (!pdata->attach_in_use)
@@ -1470,6 +1889,25 @@ static int m88ds3103_probe(struct i2c_client *client,
 	/* setup callbacks */
 	pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend;
 	pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter;
+
+	if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
+		/* enable i2c repeater for tuner */
+		m88ds3103_update_bits(dev, 0x11, 0x01, 0x01);
+
+		/* get frontend address */
+		ret = regmap_read(dev->regmap, 0x29, &utmp);
+		if (ret)
+			goto err_kfree;
+		dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1;
+		dev_err(&client->dev, "dt addr is 0x%02x", dev->dt_addr);
+
+		dev->dt_client = i2c_new_dummy_device(client->adapter, dev->dt_addr);
+		if (!dev->dt_client) {
+			ret = -ENODEV;
+			goto err_kfree;
+		}
+	}
+
 	return 0;
 err_kfree:
 	kfree(dev);
@@ -1484,6 +1922,9 @@ static int m88ds3103_remove(struct i2c_client *client)
 
 	dev_dbg(&client->dev, "\n");
 
+	if (dev->dt_client)
+		i2c_unregister_device(dev->dt_client);
+
 	i2c_mux_del_adapters(dev->muxc);
 
 	kfree(dev);
@@ -1491,7 +1932,9 @@ static int m88ds3103_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id m88ds3103_id_table[] = {
-	{"m88ds3103", 0},
+	{"m88ds3103",  M88DS3103_CHIPTYPE_3103},
+	{"m88rs6000",  M88DS3103_CHIPTYPE_RS6000},
+	{"m88ds3103b", M88DS3103_CHIPTYPE_3103B},
 	{}
 };
 MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table);
@@ -1513,3 +1956,4 @@ MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(M88DS3103_FIRMWARE);
 MODULE_FIRMWARE(M88RS6000_FIRMWARE);
+MODULE_FIRMWARE(M88DS3103B_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h
index c825032f07ab..aa5306f40201 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -16,13 +16,20 @@
 #include <linux/regmap.h>
 #include <linux/math64.h>
 
-#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw"
-#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw"
+#define M88DS3103B_FIRMWARE "dvb-demod-m88ds3103b.fw"
+#define M88DS3103_FIRMWARE  "dvb-demod-m88ds3103.fw"
+#define M88RS6000_FIRMWARE  "dvb-demod-m88rs6000.fw"
+
 #define M88RS6000_CHIP_ID 0x74
 #define M88DS3103_CHIP_ID 0x70
 
+#define M88DS3103_CHIPTYPE_3103   0
+#define M88DS3103_CHIPTYPE_RS6000 1
+#define M88DS3103_CHIPTYPE_3103B  2
+
 struct m88ds3103_dev {
 	struct i2c_client *client;
+	struct i2c_client *dt_client;
 	struct regmap_config regmap_config;
 	struct regmap *regmap;
 	struct m88ds3103_config config;
@@ -35,10 +42,13 @@ struct m88ds3103_dev {
 	struct i2c_mux_core *muxc;
 	/* auto detect chip id to do different config */
 	u8 chip_id;
+	/* chip type to differentiate m88rs6000 from m88ds3103b */
+	u8 chiptype;
 	/* main mclk is calculated for M88RS6000 dynamically */
 	s32 mclk;
 	u64 post_bit_error;
 	u64 post_bit_count;
+	u8 dt_addr;
 };
 
 struct m88ds3103_reg_val {
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] em28xx: Enable Hauppauge 461e rev2
  2020-02-01 21:48 [PATCH 0/3] m88ds3103: Add support for Montage 3103b DVB-S demod Brad Love
  2020-02-01 21:48 ` [PATCH 1/3] m88ds3103: Add support for ds3103b demod Brad Love
@ 2020-02-01 21:48 ` Brad Love
  2020-02-01 21:48 ` [PATCH 3/3] dw2102: probe for demodulator i2c address Brad Love
  2 siblings, 0 replies; 6+ messages in thread
From: Brad Love @ 2020-02-01 21:48 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love

Hauppauge 461e rev2 is a DVB-S/S2 usb device containing:
- m88ds3103b demod
- ts2022 tuner
- A8293 SEC

Device is the same as Hauppauge 461e,
except it contains updated m88ds3103b demod.

Signed-off-by: Brad Love <brad@nextdimension.cc>
---
 drivers/media/usb/em28xx/em28xx-cards.c | 18 ++++++++
 drivers/media/usb/em28xx/em28xx-dvb.c   | 60 +++++++++++++++++++++++++
 drivers/media/usb/em28xx/em28xx.h       |  1 +
 3 files changed, 79 insertions(+)

diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index def9cdd931a9..a8c321d11827 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2397,6 +2397,20 @@ const struct em28xx_board em28xx_boards[] = {
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
 	},
+	/*
+	 * 2013:0259 PCTV DVB-S2 Stick (461e_v2)
+	 * Empia EM28178, Montage M88DS3103b, Montage M88TS2022, Allegro A8293
+	 */
+	[EM28178_BOARD_PCTV_461E_V2] = {
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE |
+				 EM28XX_I2C_FREQ_400_KHZ,
+		.name          = "PCTV DVB-S2 Stick (461e v2)",
+		.tuner_type    = TUNER_ABSENT,
+		.tuner_gpio    = pctv_461e,
+		.has_dvb       = 1,
+		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+	},
 	/*
 	 * 2013:025f PCTV tripleStick (292e).
 	 * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157
@@ -2696,6 +2710,10 @@ struct usb_device_id em28xx_id_table[] = {
 			.driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE },
 	{ USB_DEVICE(0x2013, 0x0258),
 			.driver_info = EM28178_BOARD_PCTV_461E },
+	{ USB_DEVICE(0x2013, 0x0461),
+			.driver_info = EM28178_BOARD_PCTV_461E_V2 },
+	{ USB_DEVICE(0x2013, 0x0259),
+			.driver_info = EM28178_BOARD_PCTV_461E_V2 },
 	{ USB_DEVICE(0x2013, 0x025f),
 			.driver_info = EM28178_BOARD_PCTV_292E },
 	{ USB_DEVICE(0x2013, 0x0264), /* Hauppauge WinTV-soloHD 292e SE */
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 0ab6c493bc74..fb9cbfa81a84 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1219,6 +1219,61 @@ static int em28178_dvb_init_pctv_461e(struct em28xx *dev)
 	return 0;
 }
 
+static int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev)
+{
+	struct em28xx_dvb *dvb = dev->dvb;
+	struct i2c_adapter *i2c_adapter;
+	struct m88ds3103_platform_data m88ds3103_pdata = {};
+	struct ts2020_config ts2020_config = {};
+	struct a8293_platform_data a8293_pdata = {};
+
+	/* attach demod */
+	m88ds3103_pdata.clk = 27000000;
+	m88ds3103_pdata.i2c_wr_max = 33;
+	m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
+	m88ds3103_pdata.ts_clk = 16000;
+	m88ds3103_pdata.ts_clk_pol = 0;
+	m88ds3103_pdata.agc = 0x99;
+	m88ds3103_pdata.agc_inv = 0;
+	m88ds3103_pdata.spec_inv = 0;
+	dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b",
+						 &dev->i2c_adap[dev->def_i2c_bus],
+						 0x6a, &m88ds3103_pdata);
+
+	if (!dvb->i2c_client_demod)
+		return -ENODEV;
+
+	dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod);
+	i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod);
+
+	/* attach tuner */
+	ts2020_config.fe = dvb->fe[0];
+	dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022",
+						 i2c_adapter,
+						 0x60, &ts2020_config);
+	if (!dvb->i2c_client_tuner) {
+		dvb_module_release(dvb->i2c_client_demod);
+		return -ENODEV;
+	}
+
+	/* delegate signal strength measurement to tuner */
+	dvb->fe[0]->ops.read_signal_strength =
+			dvb->fe[0]->ops.tuner_ops.get_rf_strength;
+
+	/* attach SEC */
+	a8293_pdata.dvb_frontend = dvb->fe[0];
+	dvb->i2c_client_sec = dvb_module_probe("a8293", NULL,
+					       &dev->i2c_adap[dev->def_i2c_bus],
+					       0x08, &a8293_pdata);
+	if (!dvb->i2c_client_sec) {
+		dvb_module_release(dvb->i2c_client_tuner);
+		dvb_module_release(dvb->i2c_client_demod);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int em28178_dvb_init_pctv_292e(struct em28xx *dev)
 {
 	struct em28xx_dvb *dvb = dev->dvb;
@@ -1860,6 +1915,11 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		if (result)
 			goto out_free;
 		break;
+	case EM28178_BOARD_PCTV_461E_V2:
+		result = em28178_dvb_init_pctv_461e_v2(dev);
+		if (result)
+			goto out_free;
+		break;
 	case EM28178_BOARD_PCTV_292E:
 		result = em28178_dvb_init_pctv_292e(dev);
 		if (result)
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 4ecadd57dac7..acbb62397314 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -150,6 +150,7 @@
 #define EM2884_BOARD_TERRATEC_H6		  101
 #define EM2882_BOARD_ZOLID_HYBRID_TV_STICK		102
 #define EM2861_BOARD_MAGIX_VIDEOWANDLER2          103
+#define EM28178_BOARD_PCTV_461E_V2                104
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] dw2102: probe for demodulator i2c address
  2020-02-01 21:48 [PATCH 0/3] m88ds3103: Add support for Montage 3103b DVB-S demod Brad Love
  2020-02-01 21:48 ` [PATCH 1/3] m88ds3103: Add support for ds3103b demod Brad Love
  2020-02-01 21:48 ` [PATCH 2/3] em28xx: Enable Hauppauge 461e rev2 Brad Love
@ 2020-02-01 21:48 ` Brad Love
  2 siblings, 0 replies; 6+ messages in thread
From: Brad Love @ 2020-02-01 21:48 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love, Michael Bunk

This is required to support the Terratec S2 USB Box Revision 4, which
reused usb vid:pid, but has a different demodulator (m88ds3103b) at
i2c address 0x6a.

Signed-off-by: Michael Bunk <micha@freedict.org>
[fixed checkpatch issues]
Signed-off-by: Brad Love <brad@nextdimension.cc>
---
 drivers/media/usb/dvb-usb/dw2102.c | 45 ++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 8b584507dd59..1007366a295b 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -1524,6 +1524,29 @@ static int m88rs2000_frontend_attach(struct dvb_usb_adapter *adap)
 	return -EIO;
 }
 
+static int tt_s2_4600_frontend_attach_probe_demod(struct dvb_usb_device *d,
+						  const int probe_addr)
+{
+	struct dw2102_state *state = d->priv;
+
+	state->data[0] = 0x9;
+	state->data[1] = 0x1;
+	state->data[2] = 0x1;
+	state->data[3] = probe_addr;
+	state->data[4] = 0x0;
+
+	if (dvb_usb_generic_rw(d, state->data, 5, state->data, 2, 0) < 0) {
+		err("i2c probe for address 0x%x failed.", probe_addr);
+		return 0;
+	}
+
+	if (state->data[0] != 8) /* fail(7) or error, no device at address */
+		return 0;
+
+	/* probing successful */
+	return 1;
+}
+
 static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_usb_device *d = adap->dev;
@@ -1533,6 +1556,7 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
 	struct i2c_board_info board_info;
 	struct m88ds3103_platform_data m88ds3103_pdata = {};
 	struct ts2020_config ts2020_config = {};
+	int demod_addr;
 
 	mutex_lock(&d->data_mutex);
 
@@ -1570,8 +1594,22 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
 	if (dvb_usb_generic_rw(d, state->data, 1, state->data, 1, 0) < 0)
 		err("command 0x51 transfer failed.");
 
+	/* probe for demodulator i2c address */
+	demod_addr = -1;
+	if (tt_s2_4600_frontend_attach_probe_demod(d, 0x68))
+		demod_addr = 0x68;
+	else if (tt_s2_4600_frontend_attach_probe_demod(d, 0x69))
+		demod_addr = 0x69;
+	else if (tt_s2_4600_frontend_attach_probe_demod(d, 0x6a))
+		demod_addr = 0x6a;
+
 	mutex_unlock(&d->data_mutex);
 
+	if (demod_addr < 0) {
+		err("probing for demodulator failed. Is the external power switched on?");
+		return -ENODEV;
+	}
+
 	/* attach demod */
 	m88ds3103_pdata.clk = 27000000;
 	m88ds3103_pdata.i2c_wr_max = 33;
@@ -1586,8 +1624,11 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
 	m88ds3103_pdata.lnb_hv_pol = 1;
 	m88ds3103_pdata.lnb_en_pol = 0;
 	memset(&board_info, 0, sizeof(board_info));
-	strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
-	board_info.addr = 0x68;
+	if (demod_addr == 0x6a)
+		strscpy(board_info.type, "m88ds3103b", I2C_NAME_SIZE);
+	else
+		strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
+	board_info.addr = demod_addr;
 	board_info.platform_data = &m88ds3103_pdata;
 	request_module("m88ds3103");
 	client = i2c_new_client_device(&d->i2c_adap, &board_info);
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] m88ds3103: Add support for ds3103b demod
  2020-02-01 21:48 ` [PATCH 1/3] m88ds3103: Add support for ds3103b demod Brad Love
@ 2020-02-03 10:03   ` kbuild test robot
  2020-02-03 11:09   ` kbuild test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2020-02-03 10:03 UTC (permalink / raw)
  To: Brad Love; +Cc: kbuild-all, linux-media, Brad Love

[-- Attachment #1: Type: text/plain, Size: 13392 bytes --]

Hi Brad,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v5.5 next-20200203]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Brad-Love/m88ds3103-Add-support-for-Montage-3103b-DVB-S-demod/20200203-135639
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-b001-20200202 (attached as .config)
compiler: gcc-7 (Debian 7.5.0-3) 7.5.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/media/dvb-frontends/m88ds3103.c: In function 'm88ds3103_set_frontend':
>> drivers/media/dvb-frontends/m88ds3103.c:906:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
      if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
         ^
   drivers/media/dvb-frontends/m88ds3103.c:911:2: note: here
     default:
     ^~~~~~~

vim +906 drivers/media/dvb-frontends/m88ds3103.c

   623	
   624	static int m88ds3103_set_frontend(struct dvb_frontend *fe)
   625	{
   626		struct m88ds3103_dev *dev = fe->demodulator_priv;
   627		struct i2c_client *client = dev->client;
   628		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
   629		int ret, len;
   630		const struct m88ds3103_reg_val *init;
   631		u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */
   632		u8 buf[3];
   633		u16 u16tmp;
   634		u32 tuner_frequency_khz, target_mclk, u32tmp;
   635		s32 s32tmp;
   636		static const struct reg_sequence reset_buf[] = {
   637			{0x07, 0x80}, {0x07, 0x00}
   638		};
   639	
   640		dev_dbg(&client->dev,
   641			"delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n",
   642			c->delivery_system, c->modulation, c->frequency, c->symbol_rate,
   643			c->inversion, c->pilot, c->rolloff);
   644	
   645		if (!dev->warm) {
   646			ret = -EAGAIN;
   647			goto err;
   648		}
   649	
   650		/* reset */
   651		ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2);
   652		if (ret)
   653			goto err;
   654	
   655		/* Disable demod clock path */
   656		if (dev->chip_id == M88RS6000_CHIP_ID) {
   657			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   658				ret = regmap_read(dev->regmap, 0xb2, &u32tmp);
   659				if (ret)
   660					goto err;
   661				if (u32tmp == 0x01) {
   662					ret = regmap_write(dev->regmap, 0x00, 0x00);
   663					if (ret)
   664						goto err;
   665					ret = regmap_write(dev->regmap, 0xb2, 0x00);
   666					if (ret)
   667						goto err;
   668				}
   669			}
   670	
   671			ret = regmap_write(dev->regmap, 0x06, 0xe0);
   672			if (ret)
   673				goto err;
   674		}
   675	
   676		/* program tuner */
   677		if (fe->ops.tuner_ops.set_params) {
   678			ret = fe->ops.tuner_ops.set_params(fe);
   679			if (ret)
   680				goto err;
   681		}
   682	
   683		if (fe->ops.tuner_ops.get_frequency) {
   684			ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency_khz);
   685			if (ret)
   686				goto err;
   687		} else {
   688			/*
   689			 * Use nominal target frequency as tuner driver does not provide
   690			 * actual frequency used. Carrier offset calculation is not
   691			 * valid.
   692			 */
   693			tuner_frequency_khz = c->frequency;
   694		}
   695	
   696		/* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */
   697		if (dev->chip_id == M88RS6000_CHIP_ID) {
   698			if (c->symbol_rate > 45010000)
   699				dev->mclk = 110250000;
   700			else
   701				dev->mclk = 96000000;
   702	
   703			if (c->delivery_system == SYS_DVBS)
   704				target_mclk = 96000000;
   705			else
   706				target_mclk = 144000000;
   707	
   708			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   709				m88ds3103b_select_mclk(dev);
   710				m88ds3103b_set_mclk(dev, target_mclk / 1000);
   711			}
   712	
   713			/* Enable demod clock path */
   714			ret = regmap_write(dev->regmap, 0x06, 0x00);
   715			if (ret)
   716				goto err;
   717			usleep_range(10000, 20000);
   718		} else {
   719		/* set M88DS3103 mclk and ts mclk. */
   720			dev->mclk = 96000000;
   721	
   722			switch (dev->cfg->ts_mode) {
   723			case M88DS3103_TS_SERIAL:
   724			case M88DS3103_TS_SERIAL_D7:
   725				target_mclk = dev->cfg->ts_clk;
   726				break;
   727			case M88DS3103_TS_PARALLEL:
   728			case M88DS3103_TS_CI:
   729				if (c->delivery_system == SYS_DVBS)
   730					target_mclk = 96000000;
   731				else {
   732					if (c->symbol_rate < 18000000)
   733						target_mclk = 96000000;
   734					else if (c->symbol_rate < 28000000)
   735						target_mclk = 144000000;
   736					else
   737						target_mclk = 192000000;
   738				}
   739				break;
   740			default:
   741				dev_dbg(&client->dev, "invalid ts_mode\n");
   742				ret = -EINVAL;
   743				goto err;
   744			}
   745	
   746			switch (target_mclk) {
   747			case 96000000:
   748				u8tmp1 = 0x02; /* 0b10 */
   749				u8tmp2 = 0x01; /* 0b01 */
   750				break;
   751			case 144000000:
   752				u8tmp1 = 0x00; /* 0b00 */
   753				u8tmp2 = 0x01; /* 0b01 */
   754				break;
   755			case 192000000:
   756				u8tmp1 = 0x03; /* 0b11 */
   757				u8tmp2 = 0x00; /* 0b00 */
   758				break;
   759			}
   760			ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
   761			if (ret)
   762				goto err;
   763			ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
   764			if (ret)
   765				goto err;
   766		}
   767	
   768		ret = regmap_write(dev->regmap, 0xb2, 0x01);
   769		if (ret)
   770			goto err;
   771	
   772		ret = regmap_write(dev->regmap, 0x00, 0x01);
   773		if (ret)
   774			goto err;
   775	
   776		switch (c->delivery_system) {
   777		case SYS_DVBS:
   778			if (dev->chip_id == M88RS6000_CHIP_ID) {
   779				len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals);
   780				init = m88rs6000_dvbs_init_reg_vals;
   781			} else {
   782				len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals);
   783				init = m88ds3103_dvbs_init_reg_vals;
   784			}
   785			break;
   786		case SYS_DVBS2:
   787			if (dev->chip_id == M88RS6000_CHIP_ID) {
   788				len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals);
   789				init = m88rs6000_dvbs2_init_reg_vals;
   790			} else {
   791				len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals);
   792				init = m88ds3103_dvbs2_init_reg_vals;
   793			}
   794			break;
   795		default:
   796			dev_dbg(&client->dev, "invalid delivery_system\n");
   797			ret = -EINVAL;
   798			goto err;
   799		}
   800	
   801		/* program init table */
   802		if (c->delivery_system != dev->delivery_system) {
   803			ret = m88ds3103_wr_reg_val_tab(dev, init, len);
   804			if (ret)
   805				goto err;
   806		}
   807	
   808		if (dev->chip_id == M88RS6000_CHIP_ID) {
   809			if (c->delivery_system == SYS_DVBS2 &&
   810			    c->symbol_rate <= 5000000) {
   811				ret = regmap_write(dev->regmap, 0xc0, 0x04);
   812				if (ret)
   813					goto err;
   814				buf[0] = 0x09;
   815				buf[1] = 0x22;
   816				buf[2] = 0x88;
   817				ret = regmap_bulk_write(dev->regmap, 0x8a, buf, 3);
   818				if (ret)
   819					goto err;
   820			}
   821			ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
   822			if (ret)
   823				goto err;
   824	
   825			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   826				buf[0] = m88ds3103b_dt_read(dev, 0x15);
   827				buf[1] = m88ds3103b_dt_read(dev, 0x16);
   828	
   829				if (c->symbol_rate > 45010000) {
   830					buf[0] &= ~0x03;
   831					buf[0] |= 0x02;
   832					buf[0] |= ((147 - 32) >> 8) & 0x01;
   833					buf[1] = (147 - 32) & 0xFF;
   834	
   835					dev->mclk = 110250 * 1000;
   836				} else {
   837					buf[0] &= ~0x03;
   838					buf[0] |= ((128 - 32) >> 8) & 0x01;
   839					buf[1] = (128 - 32) & 0xFF;
   840	
   841					dev->mclk = 96000 * 1000;
   842				}
   843				m88ds3103b_dt_write(dev, 0x15, buf[0]);
   844				m88ds3103b_dt_write(dev, 0x16, buf[1]);
   845	
   846				regmap_read(dev->regmap, 0x30, &u32tmp);
   847				u32tmp &= ~0x80;
   848				regmap_write(dev->regmap, 0x30, u32tmp & 0xff);
   849			}
   850	
   851			ret = regmap_write(dev->regmap, 0xf1, 0x01);
   852			if (ret)
   853				goto err;
   854	
   855			if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) {
   856				ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
   857				if (ret)
   858					goto err;
   859			}
   860		}
   861	
   862		switch (dev->cfg->ts_mode) {
   863		case M88DS3103_TS_SERIAL:
   864			u8tmp1 = 0x00;
   865			u8tmp = 0x06;
   866			break;
   867		case M88DS3103_TS_SERIAL_D7:
   868			u8tmp1 = 0x20;
   869			u8tmp = 0x06;
   870			break;
   871		case M88DS3103_TS_PARALLEL:
   872			u8tmp = 0x02;
   873			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   874				u8tmp = 0x01;
   875				u8tmp1 = 0x01;
   876			}
   877			break;
   878		case M88DS3103_TS_CI:
   879			u8tmp = 0x03;
   880			break;
   881		default:
   882			dev_dbg(&client->dev, "invalid ts_mode\n");
   883			ret = -EINVAL;
   884			goto err;
   885		}
   886	
   887		if (dev->cfg->ts_clk_pol)
   888			u8tmp |= 0x40;
   889	
   890		/* TS mode */
   891		ret = regmap_write(dev->regmap, 0xfd, u8tmp);
   892		if (ret)
   893			goto err;
   894	
   895		switch (dev->cfg->ts_mode) {
   896		case M88DS3103_TS_SERIAL:
   897		case M88DS3103_TS_SERIAL_D7:
   898			ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
   899			if (ret)
   900				goto err;
   901			u16tmp = 0;
   902			u8tmp1 = 0x3f;
   903			u8tmp2 = 0x3f;
   904			break;
   905		case M88DS3103_TS_PARALLEL:
 > 906			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   907				ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1);
   908				if (ret)
   909					goto err;
   910			}
   911		default:
   912			u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk);
   913			u8tmp1 = u16tmp / 2 - 1;
   914			u8tmp2 = DIV_ROUND_UP(u16tmp, 2) - 1;
   915		}
   916	
   917		dev_dbg(&client->dev, "target_mclk=%u ts_clk=%u ts_clk_divide_ratio=%u\n",
   918			target_mclk, dev->cfg->ts_clk, u16tmp);
   919	
   920		/* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */
   921		/* u8tmp2[5:0] => ea[5:0] */
   922		u8tmp = (u8tmp1 >> 2) & 0x0f;
   923		ret = regmap_update_bits(dev->regmap, 0xfe, 0x0f, u8tmp);
   924		if (ret)
   925			goto err;
   926		u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0;
   927		ret = regmap_write(dev->regmap, 0xea, u8tmp);
   928		if (ret)
   929			goto err;
   930	
   931		if (c->symbol_rate <= 3000000)
   932			u8tmp = 0x20;
   933		else if (c->symbol_rate <= 10000000)
   934			u8tmp = 0x10;
   935		else
   936			u8tmp = 0x06;
   937	
   938		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B)
   939			m88ds3103b_set_mclk(dev, target_mclk / 1000);
   940	
   941		ret = regmap_write(dev->regmap, 0xc3, 0x08);
   942		if (ret)
   943			goto err;
   944	
   945		ret = regmap_write(dev->regmap, 0xc8, u8tmp);
   946		if (ret)
   947			goto err;
   948	
   949		ret = regmap_write(dev->regmap, 0xc4, 0x08);
   950		if (ret)
   951			goto err;
   952	
   953		ret = regmap_write(dev->regmap, 0xc7, 0x00);
   954		if (ret)
   955			goto err;
   956	
   957		u16tmp = DIV_ROUND_CLOSEST_ULL((u64)c->symbol_rate * 0x10000, dev->mclk);
   958		buf[0] = (u16tmp >> 0) & 0xff;
   959		buf[1] = (u16tmp >> 8) & 0xff;
   960		ret = regmap_bulk_write(dev->regmap, 0x61, buf, 2);
   961		if (ret)
   962			goto err;
   963	
   964		ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
   965		if (ret)
   966			goto err;
   967	
   968		ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
   969		if (ret)
   970			goto err;
   971	
   972		ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc);
   973		if (ret)
   974			goto err;
   975	
   976		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   977			/* enable/disable 192M LDPC clock */
   978			ret = m88ds3103_update_bits(dev, 0x29, 0x10,
   979						(c->delivery_system == SYS_DVBS) ? 0x10 : 0x0);
   980			if (ret)
   981				goto err;
   982	
   983			ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08);
   984		}
   985	
   986		dev_dbg(&client->dev, "carrier offset=%d\n",
   987			(tuner_frequency_khz - c->frequency));
   988	
   989		/* Use 32-bit calc as there is no s64 version of DIV_ROUND_CLOSEST() */
   990		s32tmp = 0x10000 * (tuner_frequency_khz - c->frequency);
   991		s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk / 1000);
   992		buf[0] = (s32tmp >> 0) & 0xff;
   993		buf[1] = (s32tmp >> 8) & 0xff;
   994		ret = regmap_bulk_write(dev->regmap, 0x5e, buf, 2);
   995		if (ret)
   996			goto err;
   997	
   998		ret = regmap_write(dev->regmap, 0x00, 0x00);
   999		if (ret)
  1000			goto err;
  1001	
  1002		ret = regmap_write(dev->regmap, 0xb2, 0x00);
  1003		if (ret)
  1004			goto err;
  1005	
  1006		dev->delivery_system = c->delivery_system;
  1007	
  1008		return 0;
  1009	err:
  1010		dev_dbg(&client->dev, "failed=%d\n", ret);
  1011		return ret;
  1012	}
  1013	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37816 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] m88ds3103: Add support for ds3103b demod
  2020-02-01 21:48 ` [PATCH 1/3] m88ds3103: Add support for ds3103b demod Brad Love
  2020-02-03 10:03   ` kbuild test robot
@ 2020-02-03 11:09   ` kbuild test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2020-02-03 11:09 UTC (permalink / raw)
  To: Brad Love; +Cc: kbuild-all, linux-media, Brad Love

[-- Attachment #1: Type: text/plain, Size: 17813 bytes --]

Hi Brad,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v5.5 next-20200203]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Brad-Love/m88ds3103-Add-support-for-Montage-3103b-DVB-S-demod/20200203-135639
base:   git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-d002-20200202 (attached as .config)
compiler: gcc-7 (Debian 7.5.0-3) 7.5.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from arch/x86/include/asm/current.h:5:0,
                    from include/linux/sched.h:12,
                    from include/media/dvb_frontend.h:36,
                    from drivers/media/dvb-frontends/m88ds3103_priv.h:11,
                    from drivers/media/dvb-frontends/m88ds3103.c:8:
   drivers/media/dvb-frontends/m88ds3103.c: In function 'm88ds3103_set_frontend':
   include/linux/compiler.h:56:26: warning: this statement may fall through [-Wimplicit-fallthrough=]
    #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                             ^
>> drivers/media/dvb-frontends/m88ds3103.c:906:3: note: in expansion of macro 'if'
      if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
      ^~
   drivers/media/dvb-frontends/m88ds3103.c:911:2: note: here
     default:
     ^~~~~~~
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
   Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
   Cyclomatic Complexity 1 include/linux/math64.h:div_u64_rem
   Cyclomatic Complexity 1 include/linux/math64.h:div_s64_rem
   Cyclomatic Complexity 1 include/linux/math64.h:div_u64
   Cyclomatic Complexity 1 include/linux/math64.h:div_s64
   Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR
   Cyclomatic Complexity 1 include/linux/jiffies.h:_msecs_to_jiffies
   Cyclomatic Complexity 7 include/linux/jiffies.h:msecs_to_jiffies
   Cyclomatic Complexity 4 include/linux/slab.h:kmalloc_type
   Cyclomatic Complexity 84 include/linux/slab.h:kmalloc_index
   Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_large
   Cyclomatic Complexity 10 include/linux/slab.h:kmalloc
   Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
   Cyclomatic Complexity 1 include/linux/device.h:dev_get_drvdata
   Cyclomatic Complexity 1 include/linux/device.h:dev_set_drvdata
   Cyclomatic Complexity 1 include/linux/i2c.h:i2c_get_clientdata
   Cyclomatic Complexity 1 include/linux/i2c.h:i2c_set_clientdata
   Cyclomatic Complexity 1 include/linux/i2c-mux.h:i2c_mux_priv
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_read_ber
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_tune_settings
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_dvb_frontend
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_i2c_adapter
   Cyclomatic Complexity 4 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_agc_pwm
   Cyclomatic Complexity 4 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_read_snr
   Cyclomatic Complexity 74 include/asm-generic/getorder.h:get_order
   Cyclomatic Complexity 3 include/linux/err.h:IS_ERR_OR_NULL
   Cyclomatic Complexity 3 include/linux/i2c.h:i2c_client_has_driver
   Cyclomatic Complexity 3 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_attach
   Cyclomatic Complexity 1 include/linux/err.h:IS_ERR
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_driver_init
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_release
   Cyclomatic Complexity 4 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_remove
   Cyclomatic Complexity 19 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_wr_reg_val_tab
   Cyclomatic Complexity 56 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_get_frontend
   Cyclomatic Complexity 7 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_update_bits
   Cyclomatic Complexity 56 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_probe
   Cyclomatic Complexity 10 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_set_voltage
   Cyclomatic Complexity 12 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_set_tone
   Cyclomatic Complexity 31 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_diseqc_send_burst
   Cyclomatic Complexity 35 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_diseqc_send_master_cmd
   Cyclomatic Complexity 16 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_sleep
   Cyclomatic Complexity 82 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_read_status
   Cyclomatic Complexity 6 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_dt_read
   Cyclomatic Complexity 6 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_dt_write
   Cyclomatic Complexity 30 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_select_mclk
   Cyclomatic Complexity 79 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103b_set_mclk
   Cyclomatic Complexity 210 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_set_frontend
   Cyclomatic Complexity 50 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_init
   Cyclomatic Complexity 7 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_select
   Cyclomatic Complexity 1 drivers/media/dvb-frontends/m88ds3103.c:m88ds3103_driver_exit

vim +/if +906 drivers/media/dvb-frontends/m88ds3103.c

   623	
   624	static int m88ds3103_set_frontend(struct dvb_frontend *fe)
   625	{
   626		struct m88ds3103_dev *dev = fe->demodulator_priv;
   627		struct i2c_client *client = dev->client;
   628		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
   629		int ret, len;
   630		const struct m88ds3103_reg_val *init;
   631		u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */
   632		u8 buf[3];
   633		u16 u16tmp;
   634		u32 tuner_frequency_khz, target_mclk, u32tmp;
   635		s32 s32tmp;
   636		static const struct reg_sequence reset_buf[] = {
   637			{0x07, 0x80}, {0x07, 0x00}
   638		};
   639	
   640		dev_dbg(&client->dev,
   641			"delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n",
   642			c->delivery_system, c->modulation, c->frequency, c->symbol_rate,
   643			c->inversion, c->pilot, c->rolloff);
   644	
   645		if (!dev->warm) {
   646			ret = -EAGAIN;
   647			goto err;
   648		}
   649	
   650		/* reset */
   651		ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2);
   652		if (ret)
   653			goto err;
   654	
   655		/* Disable demod clock path */
   656		if (dev->chip_id == M88RS6000_CHIP_ID) {
   657			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   658				ret = regmap_read(dev->regmap, 0xb2, &u32tmp);
   659				if (ret)
   660					goto err;
   661				if (u32tmp == 0x01) {
   662					ret = regmap_write(dev->regmap, 0x00, 0x00);
   663					if (ret)
   664						goto err;
   665					ret = regmap_write(dev->regmap, 0xb2, 0x00);
   666					if (ret)
   667						goto err;
   668				}
   669			}
   670	
   671			ret = regmap_write(dev->regmap, 0x06, 0xe0);
   672			if (ret)
   673				goto err;
   674		}
   675	
   676		/* program tuner */
   677		if (fe->ops.tuner_ops.set_params) {
   678			ret = fe->ops.tuner_ops.set_params(fe);
   679			if (ret)
   680				goto err;
   681		}
   682	
   683		if (fe->ops.tuner_ops.get_frequency) {
   684			ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency_khz);
   685			if (ret)
   686				goto err;
   687		} else {
   688			/*
   689			 * Use nominal target frequency as tuner driver does not provide
   690			 * actual frequency used. Carrier offset calculation is not
   691			 * valid.
   692			 */
   693			tuner_frequency_khz = c->frequency;
   694		}
   695	
   696		/* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */
   697		if (dev->chip_id == M88RS6000_CHIP_ID) {
   698			if (c->symbol_rate > 45010000)
   699				dev->mclk = 110250000;
   700			else
   701				dev->mclk = 96000000;
   702	
   703			if (c->delivery_system == SYS_DVBS)
   704				target_mclk = 96000000;
   705			else
   706				target_mclk = 144000000;
   707	
   708			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   709				m88ds3103b_select_mclk(dev);
   710				m88ds3103b_set_mclk(dev, target_mclk / 1000);
   711			}
   712	
   713			/* Enable demod clock path */
   714			ret = regmap_write(dev->regmap, 0x06, 0x00);
   715			if (ret)
   716				goto err;
   717			usleep_range(10000, 20000);
   718		} else {
   719		/* set M88DS3103 mclk and ts mclk. */
   720			dev->mclk = 96000000;
   721	
   722			switch (dev->cfg->ts_mode) {
   723			case M88DS3103_TS_SERIAL:
   724			case M88DS3103_TS_SERIAL_D7:
   725				target_mclk = dev->cfg->ts_clk;
   726				break;
   727			case M88DS3103_TS_PARALLEL:
   728			case M88DS3103_TS_CI:
   729				if (c->delivery_system == SYS_DVBS)
   730					target_mclk = 96000000;
   731				else {
   732					if (c->symbol_rate < 18000000)
   733						target_mclk = 96000000;
   734					else if (c->symbol_rate < 28000000)
   735						target_mclk = 144000000;
   736					else
   737						target_mclk = 192000000;
   738				}
   739				break;
   740			default:
   741				dev_dbg(&client->dev, "invalid ts_mode\n");
   742				ret = -EINVAL;
   743				goto err;
   744			}
   745	
   746			switch (target_mclk) {
   747			case 96000000:
   748				u8tmp1 = 0x02; /* 0b10 */
   749				u8tmp2 = 0x01; /* 0b01 */
   750				break;
   751			case 144000000:
   752				u8tmp1 = 0x00; /* 0b00 */
   753				u8tmp2 = 0x01; /* 0b01 */
   754				break;
   755			case 192000000:
   756				u8tmp1 = 0x03; /* 0b11 */
   757				u8tmp2 = 0x00; /* 0b00 */
   758				break;
   759			}
   760			ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
   761			if (ret)
   762				goto err;
   763			ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
   764			if (ret)
   765				goto err;
   766		}
   767	
   768		ret = regmap_write(dev->regmap, 0xb2, 0x01);
   769		if (ret)
   770			goto err;
   771	
   772		ret = regmap_write(dev->regmap, 0x00, 0x01);
   773		if (ret)
   774			goto err;
   775	
   776		switch (c->delivery_system) {
   777		case SYS_DVBS:
   778			if (dev->chip_id == M88RS6000_CHIP_ID) {
   779				len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals);
   780				init = m88rs6000_dvbs_init_reg_vals;
   781			} else {
   782				len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals);
   783				init = m88ds3103_dvbs_init_reg_vals;
   784			}
   785			break;
   786		case SYS_DVBS2:
   787			if (dev->chip_id == M88RS6000_CHIP_ID) {
   788				len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals);
   789				init = m88rs6000_dvbs2_init_reg_vals;
   790			} else {
   791				len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals);
   792				init = m88ds3103_dvbs2_init_reg_vals;
   793			}
   794			break;
   795		default:
   796			dev_dbg(&client->dev, "invalid delivery_system\n");
   797			ret = -EINVAL;
   798			goto err;
   799		}
   800	
   801		/* program init table */
   802		if (c->delivery_system != dev->delivery_system) {
   803			ret = m88ds3103_wr_reg_val_tab(dev, init, len);
   804			if (ret)
   805				goto err;
   806		}
   807	
   808		if (dev->chip_id == M88RS6000_CHIP_ID) {
   809			if (c->delivery_system == SYS_DVBS2 &&
   810			    c->symbol_rate <= 5000000) {
   811				ret = regmap_write(dev->regmap, 0xc0, 0x04);
   812				if (ret)
   813					goto err;
   814				buf[0] = 0x09;
   815				buf[1] = 0x22;
   816				buf[2] = 0x88;
   817				ret = regmap_bulk_write(dev->regmap, 0x8a, buf, 3);
   818				if (ret)
   819					goto err;
   820			}
   821			ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
   822			if (ret)
   823				goto err;
   824	
   825			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   826				buf[0] = m88ds3103b_dt_read(dev, 0x15);
   827				buf[1] = m88ds3103b_dt_read(dev, 0x16);
   828	
   829				if (c->symbol_rate > 45010000) {
   830					buf[0] &= ~0x03;
   831					buf[0] |= 0x02;
   832					buf[0] |= ((147 - 32) >> 8) & 0x01;
   833					buf[1] = (147 - 32) & 0xFF;
   834	
   835					dev->mclk = 110250 * 1000;
   836				} else {
   837					buf[0] &= ~0x03;
   838					buf[0] |= ((128 - 32) >> 8) & 0x01;
   839					buf[1] = (128 - 32) & 0xFF;
   840	
   841					dev->mclk = 96000 * 1000;
   842				}
   843				m88ds3103b_dt_write(dev, 0x15, buf[0]);
   844				m88ds3103b_dt_write(dev, 0x16, buf[1]);
   845	
   846				regmap_read(dev->regmap, 0x30, &u32tmp);
   847				u32tmp &= ~0x80;
   848				regmap_write(dev->regmap, 0x30, u32tmp & 0xff);
   849			}
   850	
   851			ret = regmap_write(dev->regmap, 0xf1, 0x01);
   852			if (ret)
   853				goto err;
   854	
   855			if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) {
   856				ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
   857				if (ret)
   858					goto err;
   859			}
   860		}
   861	
   862		switch (dev->cfg->ts_mode) {
   863		case M88DS3103_TS_SERIAL:
   864			u8tmp1 = 0x00;
   865			u8tmp = 0x06;
   866			break;
   867		case M88DS3103_TS_SERIAL_D7:
   868			u8tmp1 = 0x20;
   869			u8tmp = 0x06;
   870			break;
   871		case M88DS3103_TS_PARALLEL:
   872			u8tmp = 0x02;
   873			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   874				u8tmp = 0x01;
   875				u8tmp1 = 0x01;
   876			}
   877			break;
   878		case M88DS3103_TS_CI:
   879			u8tmp = 0x03;
   880			break;
   881		default:
   882			dev_dbg(&client->dev, "invalid ts_mode\n");
   883			ret = -EINVAL;
   884			goto err;
   885		}
   886	
   887		if (dev->cfg->ts_clk_pol)
   888			u8tmp |= 0x40;
   889	
   890		/* TS mode */
   891		ret = regmap_write(dev->regmap, 0xfd, u8tmp);
   892		if (ret)
   893			goto err;
   894	
   895		switch (dev->cfg->ts_mode) {
   896		case M88DS3103_TS_SERIAL:
   897		case M88DS3103_TS_SERIAL_D7:
   898			ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
   899			if (ret)
   900				goto err;
   901			u16tmp = 0;
   902			u8tmp1 = 0x3f;
   903			u8tmp2 = 0x3f;
   904			break;
   905		case M88DS3103_TS_PARALLEL:
 > 906			if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   907				ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1);
   908				if (ret)
   909					goto err;
   910			}
   911		default:
   912			u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk);
   913			u8tmp1 = u16tmp / 2 - 1;
   914			u8tmp2 = DIV_ROUND_UP(u16tmp, 2) - 1;
   915		}
   916	
   917		dev_dbg(&client->dev, "target_mclk=%u ts_clk=%u ts_clk_divide_ratio=%u\n",
   918			target_mclk, dev->cfg->ts_clk, u16tmp);
   919	
   920		/* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */
   921		/* u8tmp2[5:0] => ea[5:0] */
   922		u8tmp = (u8tmp1 >> 2) & 0x0f;
   923		ret = regmap_update_bits(dev->regmap, 0xfe, 0x0f, u8tmp);
   924		if (ret)
   925			goto err;
   926		u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0;
   927		ret = regmap_write(dev->regmap, 0xea, u8tmp);
   928		if (ret)
   929			goto err;
   930	
   931		if (c->symbol_rate <= 3000000)
   932			u8tmp = 0x20;
   933		else if (c->symbol_rate <= 10000000)
   934			u8tmp = 0x10;
   935		else
   936			u8tmp = 0x06;
   937	
   938		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B)
   939			m88ds3103b_set_mclk(dev, target_mclk / 1000);
   940	
   941		ret = regmap_write(dev->regmap, 0xc3, 0x08);
   942		if (ret)
   943			goto err;
   944	
   945		ret = regmap_write(dev->regmap, 0xc8, u8tmp);
   946		if (ret)
   947			goto err;
   948	
   949		ret = regmap_write(dev->regmap, 0xc4, 0x08);
   950		if (ret)
   951			goto err;
   952	
   953		ret = regmap_write(dev->regmap, 0xc7, 0x00);
   954		if (ret)
   955			goto err;
   956	
   957		u16tmp = DIV_ROUND_CLOSEST_ULL((u64)c->symbol_rate * 0x10000, dev->mclk);
   958		buf[0] = (u16tmp >> 0) & 0xff;
   959		buf[1] = (u16tmp >> 8) & 0xff;
   960		ret = regmap_bulk_write(dev->regmap, 0x61, buf, 2);
   961		if (ret)
   962			goto err;
   963	
   964		ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
   965		if (ret)
   966			goto err;
   967	
   968		ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
   969		if (ret)
   970			goto err;
   971	
   972		ret = regmap_write(dev->regmap, 0x33, dev->cfg->agc);
   973		if (ret)
   974			goto err;
   975	
   976		if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) {
   977			/* enable/disable 192M LDPC clock */
   978			ret = m88ds3103_update_bits(dev, 0x29, 0x10,
   979						(c->delivery_system == SYS_DVBS) ? 0x10 : 0x0);
   980			if (ret)
   981				goto err;
   982	
   983			ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08);
   984		}
   985	
   986		dev_dbg(&client->dev, "carrier offset=%d\n",
   987			(tuner_frequency_khz - c->frequency));
   988	
   989		/* Use 32-bit calc as there is no s64 version of DIV_ROUND_CLOSEST() */
   990		s32tmp = 0x10000 * (tuner_frequency_khz - c->frequency);
   991		s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk / 1000);
   992		buf[0] = (s32tmp >> 0) & 0xff;
   993		buf[1] = (s32tmp >> 8) & 0xff;
   994		ret = regmap_bulk_write(dev->regmap, 0x5e, buf, 2);
   995		if (ret)
   996			goto err;
   997	
   998		ret = regmap_write(dev->regmap, 0x00, 0x00);
   999		if (ret)
  1000			goto err;
  1001	
  1002		ret = regmap_write(dev->regmap, 0xb2, 0x00);
  1003		if (ret)
  1004			goto err;
  1005	
  1006		dev->delivery_system = c->delivery_system;
  1007	
  1008		return 0;
  1009	err:
  1010		dev_dbg(&client->dev, "failed=%d\n", ret);
  1011		return ret;
  1012	}
  1013	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29766 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-02-03 11:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-01 21:48 [PATCH 0/3] m88ds3103: Add support for Montage 3103b DVB-S demod Brad Love
2020-02-01 21:48 ` [PATCH 1/3] m88ds3103: Add support for ds3103b demod Brad Love
2020-02-03 10:03   ` kbuild test robot
2020-02-03 11:09   ` kbuild test robot
2020-02-01 21:48 ` [PATCH 2/3] em28xx: Enable Hauppauge 461e rev2 Brad Love
2020-02-01 21:48 ` [PATCH 3/3] dw2102: probe for demodulator i2c address Brad Love

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).