* [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).