From 6ca28e5556ac5786fe7580f9c1e8e83fb3a93e2e Mon Sep 17 00:00:00 2001 From: CvH Date: Sun, 26 Aug 2018 17:25:32 +0200 Subject: [PATCH] dvb-latest: initial package --- .../patches/media_tree-01-hauppauge.patch | 1449 +++++++++++++++++ .../{hauppauge => dvb-latest}/changelog.txt | 0 .../dvb/dvb-latest/icon/icon.png | Bin 0 -> 36366 bytes .../dvb/dvb-latest/package.mk | 40 + ...r.dvb.dvb-latest-01-remove-rmmod.pl.patch} | 0 .../source/default.py | 0 .../dvb/hauppauge/icon/icon.png | Bin 23076 -> 0 bytes projects/Generic/options | 2 +- 8 files changed, 1490 insertions(+), 1 deletion(-) create mode 100644 packages/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-hauppauge.patch rename packages/linux-driver-addons/dvb/{hauppauge => dvb-latest}/changelog.txt (100%) create mode 100644 packages/linux-driver-addons/dvb/dvb-latest/icon/icon.png create mode 100644 packages/linux-driver-addons/dvb/dvb-latest/package.mk rename packages/linux-driver-addons/dvb/{hauppauge/patches/driver.dvb.hauppauge-01-remove-rmmod.pl.patch => dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch} (100%) rename packages/linux-driver-addons/dvb/{hauppauge => dvb-latest}/source/default.py (100%) delete mode 100644 packages/linux-driver-addons/dvb/hauppauge/icon/icon.png diff --git a/packages/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-hauppauge.patch b/packages/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-hauppauge.patch new file mode 100644 index 0000000000..44327c7c63 --- /dev/null +++ b/packages/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-hauppauge.patch @@ -0,0 +1,1449 @@ +Combined patches from https://github.com/b-rad-NDi/Ubuntu-media-tree-kernel-builder +to support all kind of Hauppauge DVB cards. + +diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c +index 0e1f5da..409db8e 100644 +--- a/drivers/media/dvb-frontends/lgdt3306a.c ++++ b/drivers/media/dvb-frontends/lgdt3306a.c +@@ -855,6 +855,7 @@ static int lgdt3306a_fe_sleep(struct dvb_frontend *fe) + static int lgdt3306a_init(struct dvb_frontend *fe) + { + struct lgdt3306a_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u8 val; + int ret; + +@@ -1006,6 +1007,9 @@ static int lgdt3306a_init(struct dvb_frontend *fe) + ret = lgdt3306a_sleep(state); + lg_chkerr(ret); + ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ + fail: + return ret; + } +@@ -1606,6 +1610,7 @@ static int lgdt3306a_read_status(struct dvb_frontend *fe, + enum fe_status *status) + { + struct lgdt3306a_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u16 strength = 0; + int ret = 0; + +@@ -1646,6 +1651,15 @@ static int lgdt3306a_read_status(struct dvb_frontend *fe, + default: + ret = -EINVAL; + } ++ ++ if (*status & FE_HAS_SYNC) { ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_DECIBEL; ++ c->cnr.stat[0].svalue = lgdt3306a_calculate_snr_x100(state) * 10; ++ } else { ++ c->cnr.len = 1; ++ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ } + } + return ret; + } +diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c +index 324493e..4d43424 100644 +--- a/drivers/media/dvb-frontends/si2168.c ++++ b/drivers/media/dvb-frontends/si2168.c +@@ -18,6 +18,10 @@ + + #include "si2168_priv.h" + ++static int dvbt_auto_plp = 1; ++module_param(dvbt_auto_plp, int, 0644); ++MODULE_PARM_DESC(dvbt_auto_plp, "if set, the PLP is set to auto detect DVB-T and DVB-T2 signals"); ++ + static const struct dvb_frontend_ops si2168_ops; + + /* execute firmware command */ +@@ -106,13 +110,12 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) + return ret; + } + +-static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) ++static int si2168_get_status(struct dvb_frontend *fe, enum fe_status *status) + { + struct i2c_client *client = fe->demodulator_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); + struct dtv_frontend_properties *c = &fe->dtv_property_cache; +- int ret, i; +- unsigned int utmp, utmp1, utmp2; ++ int ret, sys; + struct si2168_cmd cmd; + + *status = 0; +@@ -122,7 +125,23 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + goto err; + } + +- switch (c->delivery_system) { ++ sys = c->delivery_system; ++ ++ /* check if we found DVB-T2 during DVB-T tuning */ ++ if (dvbt_auto_plp && sys == SYS_DVBT) { ++ memcpy(cmd.args, "\x87\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 8; ++ ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ if ((cmd.args[3] & 0x0f) == 7) ++ sys = SYS_DVBT2; ++ } ++ ++ switch (sys) { + case SYS_DVBT: + memcpy(cmd.args, "\xa0\x01", 2); + cmd.wlen = 2; +@@ -144,9 +163,29 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + } + + ret = si2168_cmd_execute(client, &cmd); ++ if (dvbt_auto_plp && (ret == -EREMOTEIO)) { ++ /* In auto-PLP mode it is possible to read 0x8701 while ++ * the frontend is in switchover transition. This causes ++ * a status read failure, due to incorrect system. Check ++ * the other sys if we hit this race condition. ++ */ ++ if (sys == SYS_DVBT) { ++ memcpy(cmd.args, "\x50\x01", 2); /* DVB-T2 */ ++ cmd.wlen = 2; ++ cmd.rlen = 14; ++ ret = si2168_cmd_execute(client, &cmd); ++ } else if (sys == SYS_DVBT2) { ++ memcpy(cmd.args, "\xa0\x01", 2); /* DVB-T */ ++ cmd.wlen = 2; ++ cmd.rlen = 13; ++ ret = si2168_cmd_execute(client, &cmd); ++ } ++ } + if (ret) + goto err; + ++ //c->delivery_system = sys; /* update delivery system in case auto-PLP */ ++ + switch ((cmd.args[2] >> 1) & 0x03) { + case 0x01: + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; +@@ -157,8 +196,6 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + break; + } + +- dev->fe_status = *status; +- + if (*status & FE_HAS_LOCK) { + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; +@@ -171,8 +208,120 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + dev_dbg(&client->dev, "status=%02x args=%*ph\n", + *status, cmd.rlen, cmd.args); + ++ dev->fe_status = *status; ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2168_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ enum fe_status status = 0; ++ u64 stat_snr; ++ int ret; ++ ++ *snr = 0; ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ ++ ret = si2168_get_status(fe, &status); ++ if (ret) ++ goto err; ++ ++ if (status & FE_HAS_LOCK) { ++ stat_snr = c->cnr.stat[0].svalue; ++ do_div(stat_snr, 100); ++ *snr = (u16)stat_snr; ++ } ++ ++ dev_dbg(&client->dev, "snr=%02x\n", *snr); ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2168_read_signal_strength(struct dvb_frontend *fe, u16 *rssi) ++{ ++ int ret = -ENOSYS; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ enum fe_status status = 0; ++ u64 stat_strength; ++ ++ *rssi = 0; ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ ++ ret = si2168_get_status(fe, &status); ++ if (ret) ++ goto err; ++ ++ if (status & FE_HAS_LOCK) { ++ if (fe->ops.tuner_ops.get_rf_strength) ++ ret = fe->ops.tuner_ops.get_rf_strength(fe, rssi); ++ else if (c->strength.len > 0) { ++ if (c->strength.stat[0].svalue < -80000) ++ *rssi = 0; ++ else { ++ stat_strength = c->strength.stat[0].svalue; ++ do_div(stat_strength, 1000); ++ *rssi = (u16)(stat_strength + 100); ++ *rssi = (*rssi > 100) ? 0xffff : ++ (u16)(((u32)*rssi) * 0xffff / 100); ++ } ++ } ++ } else { ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ } ++ ++ dev_dbg(&client->dev, "rssi=%02x\n", *rssi); ++ ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++/* ------------------------------------------------------------------------ */ ++ ++static int si2168_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ enum fe_status status = 0; ++ int ret, i; ++ unsigned int utmp, utmp1, utmp2; ++ struct si2168_cmd cmd; ++ ++ *ber = 0; ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ ++ ret = si2168_get_status(fe, &status); ++ if (ret) ++ goto err; ++ + /* BER */ +- if (*status & FE_HAS_VITERBI) { ++ if (status & FE_HAS_VITERBI) { + memcpy(cmd.args, "\x82\x00", 2); + cmd.wlen = 2; + cmd.rlen = 3; +@@ -191,6 +340,9 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + utmp1 = cmd.args[2] * utmp1; + utmp2 = 100000000; /* 10^8 */ + ++ if (cmd.args[1] != 0) ++ *ber = (cmd.args[2] * utmp1) / utmp2; ++ + dev_dbg(&client->dev, + "post_bit_error=%u post_bit_count=%u ber=%u*10^-%u\n", + utmp1, utmp2, cmd.args[2], cmd.args[1]); +@@ -204,8 +356,35 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2168_read_ucblocks(struct dvb_frontend *fe, u32 *ucb) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ enum fe_status status = 0; ++ int ret; ++ unsigned int utmp1; ++ struct si2168_cmd cmd; ++ ++ *ucb = 0; ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ ++ ret = si2168_get_status(fe, &status); ++ if (ret) ++ goto err; ++ + /* UCB */ +- if (*status & FE_HAS_SYNC) { ++ if (status & FE_HAS_SYNC) { + memcpy(cmd.args, "\x84\x01", 2); + cmd.wlen = 2; + cmd.rlen = 3; +@@ -220,11 +399,61 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) + if (utmp1 == 0xffff) + utmp1 = 0; + ++ *ucb = utmp1; ++ + c->block_error.stat[0].scale = FE_SCALE_COUNTER; + c->block_error.stat[0].uvalue += utmp1; + } else { + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } ++ return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++ ++static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) ++{ ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2168_dev *dev = i2c_get_clientdata(client); ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ u16 rssi; ++ u32 ber, ucb; ++ ++ *status = 0; ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ ++ ret = si2168_get_status(fe, status); ++ if (ret) ++ goto err; ++ ++ if ((*status & FE_HAS_LOCK) == 0) { ++ /* No lock, reset all statistics */ ++ c->strength.len = 1; ++ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ return 0; ++ } ++ ++ ret = si2168_read_signal_strength(fe, &rssi); ++ if (ret) ++ goto err; ++ ++ ret = si2168_read_ber(fe, &ber); ++ if (ret) ++ goto err; ++ ++ ret = si2168_read_ucblocks(fe, &ucb); ++ if (ret) ++ goto err; + + return 0; + err: +@@ -254,7 +483,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + + switch (c->delivery_system) { + case SYS_DVBT: +- delivery_system = 0x20; ++ if (dvbt_auto_plp) ++ delivery_system = 0xf0; /* T/T2 auto-detect is user friendly */ ++ else ++ delivery_system = 0x20; + break; + case SYS_DVBC_ANNEX_A: + delivery_system = 0x30; +@@ -324,6 +556,16 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + ret = si2168_cmd_execute(client, &cmd); + if (ret) + goto err; ++ } else if (dvbt_auto_plp && (c->delivery_system == SYS_DVBT)) { ++ /* select Auto PLP */ ++ cmd.args[0] = 0x52; ++ cmd.args[1] = 0; ++ cmd.args[2] = 0; /* Auto PLP */ ++ cmd.wlen = 3; ++ cmd.rlen = 1; ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; + } + + memcpy(cmd.args, "\x51\x03", 2); +@@ -363,6 +605,8 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + + memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6); + cmd.args[4] = delivery_system | bandwidth; ++ if (delivery_system == 0xf0) ++ cmd.args[5] |= 2; /* Auto detect DVB-T/T2 */ + if (dev->spectral_inversion) + cmd.args[5] |= 1; + cmd.wlen = 6; +@@ -384,6 +628,8 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + } + + memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); ++ /* BUGBUG? FW defaults to 1, but windows driver uses 30; above is 0? */ ++ cmd.args[5] = 30; + cmd.wlen = 6; + cmd.rlen = 4; + ret = si2168_cmd_execute(client, &cmd); +@@ -714,6 +960,11 @@ static const struct dvb_frontend_ops si2168_ops = { + .set_frontend = si2168_set_frontend, + + .read_status = si2168_read_status, ++ ++ .read_ber = si2168_read_ber, ++ .read_signal_strength = si2168_read_signal_strength, ++ .read_snr = si2168_read_snr, ++ .read_ucblocks = si2168_read_ucblocks, + }; + + static int si2168_probe(struct i2c_client *client, +diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c +index b168bf3..1f06119 100644 +--- a/drivers/media/i2c/cx25840/cx25840-core.c ++++ b/drivers/media/i2c/cx25840/cx25840-core.c +@@ -684,14 +684,14 @@ static void cx23885_initialize(struct i2c_client *client) + */ + cx25840_write4(client, 0x404, 0x0010253e); + +- /* CC on - Undocumented Register */ ++ /* CC on - VBI_LINE_CTRL3, FLD_VBI_MD_LINE12 */ + cx25840_write(client, state->vbi_regs_offset + 0x42f, 0x66); + + /* HVR-1250 / HVR1850 DIF related */ + /* Power everything up */ + cx25840_write4(client, 0x130, 0x0); + +- /* Undocumented */ ++ /* SRC_COMB_CFG */ + if (is_cx23888(state)) + cx25840_write4(client, 0x454, 0x6628021F); + else +@@ -1127,16 +1127,25 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp + cx25840_write4(client, 0x410, 0xffff0dbf); + cx25840_write4(client, 0x414, 0x00137d03); + +- cx25840_write4(client, state->vbi_regs_offset + 0x42c, 0x42600000); +- cx25840_write4(client, state->vbi_regs_offset + 0x430, 0x0000039b); +- cx25840_write4(client, state->vbi_regs_offset + 0x438, 0x00000000); +- +- cx25840_write4(client, state->vbi_regs_offset + 0x440, 0xF8E3E824); +- cx25840_write4(client, state->vbi_regs_offset + 0x444, 0x401040dc); +- cx25840_write4(client, state->vbi_regs_offset + 0x448, 0xcd3f02a0); +- cx25840_write4(client, state->vbi_regs_offset + 0x44c, 0x161f1000); +- cx25840_write4(client, state->vbi_regs_offset + 0x450, 0x00000802); +- ++ /* These are not VBI controls */ ++ if (is_cx23888(state)) { ++ /* 888 MISC_TIM_CTRL */ ++ cx25840_write4(client, 0x42c, 0x42600000); ++ /* 888 FIELD_COUNT */ ++ cx25840_write4(client, 0x430, 0x0000039b); ++ /* 888 VSCALE_CTRL */ ++ cx25840_write4(client, 0x438, 0x00000000); ++ /* 888 DFE_CTRL1 */ ++ cx25840_write4(client, 0x440, 0xF8E3E824); ++ /* 888 DFE_CTRL2 */ ++ cx25840_write4(client, 0x444, 0x401040dc); ++ /* 888 DFE_CTRL3 */ ++ cx25840_write4(client, 0x448, 0xcd3f02a0); ++ /* 888 PLL_CTRL */ ++ cx25840_write4(client, 0x44c, 0x161f1000); ++ /* 888 HTL_CTRL */ ++ cx25840_write4(client, 0x450, 0x00000802); ++ } + cx25840_write4(client, 0x91c, 0x01000000); + cx25840_write4(client, 0x8e0, 0x03063870); + cx25840_write4(client, 0x8d4, 0x7FFF0024); +@@ -1743,6 +1752,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) + if (is_cx2388x(state) || is_cx231xx(state)) + return 0; + ++ /* PIN_CTRL1 */ + if (enable) { + v = cx25840_read(client, 0x115) | 0x0c; + cx25840_write(client, 0x115, v); +diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c +index ed3210d..9598b99 100644 +--- a/drivers/media/pci/cx23885/cx23885-cards.c ++++ b/drivers/media/pci/cx23885/cx23885-cards.c +@@ -325,8 +325,7 @@ struct cx23885_board cx23885_boards[] = { + .name = "Hauppauge WinTV-HVR1255", + .porta = CX23885_ANALOG_VIDEO, + .portc = CX23885_MPEG_DVB, +- .tuner_type = TUNER_ABSENT, +- .tuner_addr = 0x42, /* 0x84 >> 1 */ ++ .tuner_type = TUNER_NXP_TDA18271, + .force_bff = 1, + .input = {{ + .type = CX23885_VMUX_TELEVISION, +@@ -354,8 +353,7 @@ struct cx23885_board cx23885_boards[] = { + .name = "Hauppauge WinTV-HVR1255", + .porta = CX23885_ANALOG_VIDEO, + .portc = CX23885_MPEG_DVB, +- .tuner_type = TUNER_ABSENT, +- .tuner_addr = 0x42, /* 0x84 >> 1 */ ++ .tuner_type = TUNER_NXP_TDA18271, + .force_bff = 1, + .input = {{ + .type = CX23885_VMUX_TELEVISION, +@@ -767,24 +765,48 @@ struct cx23885_board cx23885_boards[] = { + } }, + }, + [CX23885_BOARD_HAUPPAUGE_QUADHD_DVB] = { +- .name = "Hauppauge WinTV-QuadHD-DVB", ++ .name = "Hauppauge WinTV-QuadHD-DVB", ++ .porta = CX23885_ANALOG_VIDEO, + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, ++ .tuner_type = TUNER_ABSENT, ++ .force_bff = 1, ++ .input = {{ ++ .type = CX23885_VMUX_TELEVISION, ++ .vmux = CX25840_VIN7_CH3 | ++ CX25840_VIN5_CH2 | ++ CX25840_VIN2_CH1 | ++ CX25840_DIF_ON, ++ .amux = CX25840_AUDIO8, ++ } }, + }, + [CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885] = { +- .name = "Hauppauge WinTV-QuadHD-DVB(885)", ++ .name = "Hauppauge WinTV-QuadHD-DVB(885)", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, ++ .tuner_type = TUNER_ABSENT, + }, + [CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC] = { +- .name = "Hauppauge WinTV-QuadHD-ATSC", ++ .name = "Hauppauge WinTV-QuadHD-ATSC", ++ .porta = CX23885_ANALOG_VIDEO, + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, ++ .tuner_type = TUNER_ABSENT, ++ .force_bff = 1, ++ .input = {{ ++ .type = CX23885_VMUX_TELEVISION, ++ .vmux = CX25840_VIN7_CH3 | ++ CX25840_VIN5_CH2 | ++ CX25840_VIN2_CH1 | ++ CX25840_DIF_ON, ++ .amux = CX25840_AUDIO8, ++ } }, + }, + [CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885] = { +- .name = "Hauppauge WinTV-QuadHD-ATSC(885)", ++ .name = "Hauppauge WinTV-QuadHD-ATSC(885)", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, ++ .tuner_type = TUNER_ABSENT, + }, + [CX23885_BOARD_HAUPPAUGE_HVR1265_K4] = { + .name = "Hauppauge WinTV-HVR-1265(161111)", +@@ -793,6 +815,13 @@ struct cx23885_board cx23885_boards[] = { + .tuner_type = TUNER_ABSENT, + .force_bff = 1, + .input = {{ ++ .type = CX23885_VMUX_TELEVISION, ++ .vmux = CX25840_VIN7_CH3 | ++ CX25840_VIN5_CH2 | ++ CX25840_VIN2_CH1 | ++ CX25840_DIF_ON, ++ .amux = CX25840_AUDIO8, ++ }, { + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN4_CH2 | +diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c +index 7d52173..9e61f23 100644 +--- a/drivers/media/pci/cx23885/cx23885-dvb.c ++++ b/drivers/media/pci/cx23885/cx23885-dvb.c +@@ -2382,6 +2382,16 @@ static int dvb_register(struct cx23885_tsport *port) + goto frontend_detach; + } + port->i2c_client_tuner = client_tuner; ++ ++ /* we only attach tuner for analog on the 888 version */ ++ if (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) { ++ pr_info("%s(): QUADHD_DVB analog setup\n", ++ __func__); ++ dev->ts1.analog_fe.tuner_priv = client_tuner; ++ memcpy(&dev->ts1.analog_fe.ops.tuner_ops, ++ &fe0->dvb.frontend->ops.tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ } + break; + + /* port c - terrestrial/cable */ +@@ -2471,6 +2481,16 @@ static int dvb_register(struct cx23885_tsport *port) + goto frontend_detach; + } + port->i2c_client_tuner = client_tuner; ++ ++ /* we only attach tuner for analog on the 888 version */ ++ if (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC) { ++ pr_info("%s(): QUADHD_ATSC analog setup\n", ++ __func__); ++ dev->ts1.analog_fe.tuner_priv = client_tuner; ++ memcpy(&dev->ts1.analog_fe.ops.tuner_ops, ++ &fe0->dvb.frontend->ops.tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ } + break; + + /* port c - terrestrial/cable */ +@@ -2542,6 +2562,11 @@ static int dvb_register(struct cx23885_tsport *port) + goto frontend_detach; + } + port->i2c_client_tuner = client_tuner; ++ ++ dev->ts1.analog_fe.tuner_priv = client_tuner; ++ memcpy(&dev->ts1.analog_fe.ops.tuner_ops, ++ &fe0->dvb.frontend->ops.tuner_ops, ++ sizeof(struct dvb_tuner_ops)); + break; + } + break; +diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c +index f8a3dea..594bdcf 100644 +--- a/drivers/media/pci/cx23885/cx23885-video.c ++++ b/drivers/media/pci/cx23885/cx23885-video.c +@@ -264,6 +264,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4) || ++ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC) || ++ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) || + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || + (dev->board == CX23885_BOARD_MYGICA_X8507) || + (dev->board == CX23885_BOARD_AVERMEDIA_HC81R) || +@@ -644,8 +646,17 @@ static int vidioc_querycap(struct file *file, void *priv, + sizeof(cap->card)); + sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); + cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_AUDIO; +- if (dev->tuner_type != TUNER_ABSENT) ++ switch (dev->board) { /* i2c device tuners */ ++ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: + cap->device_caps |= V4L2_CAP_TUNER; ++ break; ++ default: ++ if (dev->tuner_type != TUNER_ABSENT) ++ cap->device_caps |= V4L2_CAP_TUNER; ++ break; ++ } + if (vdev->vfl_type == VFL_TYPE_VBI) + cap->device_caps |= V4L2_CAP_VBI_CAPTURE; + else +@@ -882,8 +893,16 @@ static int vidioc_g_tuner(struct file *file, void *priv, + { + struct cx23885_dev *dev = video_drvdata(file); + +- if (dev->tuner_type == TUNER_ABSENT) +- return -EINVAL; ++ switch (dev->board) { /* i2c device tuners */ ++ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: ++ break; ++ default: ++ if (dev->tuner_type == TUNER_ABSENT) ++ return -EINVAL; ++ break; ++ } + if (0 != t->index) + return -EINVAL; + +@@ -898,8 +917,16 @@ static int vidioc_s_tuner(struct file *file, void *priv, + { + struct cx23885_dev *dev = video_drvdata(file); + +- if (dev->tuner_type == TUNER_ABSENT) +- return -EINVAL; ++ switch (dev->board) { /* i2c device tuners */ ++ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: ++ break; ++ default: ++ if (dev->tuner_type == TUNER_ABSENT) ++ return -EINVAL; ++ break; ++ } + if (0 != t->index) + return -EINVAL; + /* Update the A/V core */ +@@ -913,9 +940,16 @@ static int vidioc_g_frequency(struct file *file, void *priv, + { + struct cx23885_dev *dev = video_drvdata(file); + +- if (dev->tuner_type == TUNER_ABSENT) +- return -EINVAL; +- ++ switch (dev->board) { /* i2c device tuners */ ++ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: ++ break; ++ default: ++ if (dev->tuner_type == TUNER_ABSENT) ++ return -EINVAL; ++ break; ++ } + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = dev->freq; + +@@ -929,8 +963,16 @@ static int cx23885_set_freq(struct cx23885_dev *dev, const struct v4l2_frequency + struct v4l2_ctrl *mute; + int old_mute_val = 1; + +- if (dev->tuner_type == TUNER_ABSENT) +- return -EINVAL; ++ switch (dev->board) { /* i2c device tuners */ ++ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: ++ break; ++ default: ++ if (dev->tuner_type == TUNER_ABSENT) ++ return -EINVAL; ++ break; ++ } + if (unlikely(f->tuner != 0)) + return -EINVAL; + +@@ -995,7 +1037,9 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, + if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || +- (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4)) ++ (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4) || ++ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) || ++ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC)) + fe = &dev->ts1.analog_fe; + + if (fe && fe->ops.tuner_ops.set_analog_params) { +@@ -1026,6 +1070,8 @@ int cx23885_set_frequency(struct file *file, void *priv, + case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: + case CX23885_BOARD_HAUPPAUGE_HVR1850: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: ++ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: + ret = cx23885_set_freq_via_ops(dev, f); + break; + default: +diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c +index a08d8fe..26b1c3d 100644 +--- a/drivers/media/tuners/si2157.c ++++ b/drivers/media/tuners/si2157.c +@@ -56,14 +56,20 @@ static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) + break; + } + +- dev_dbg(&client->dev, "cmd execution took %d ms\n", ++ dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n", + jiffies_to_msecs(jiffies) - +- (jiffies_to_msecs(timeout) - TIMEOUT)); ++ (jiffies_to_msecs(timeout) - TIMEOUT), ++ cmd->args[0]); + + if (!((cmd->args[0] >> 7) & 0x01)) { + ret = -ETIMEDOUT; + goto err_mutex_unlock; + } ++ /* check error status bit */ ++ if (cmd->args[0] & 0x40) { ++ ret = -EAGAIN; ++ goto err_mutex_unlock; ++ } + } + + mutex_unlock(&dev->i2c_mutex); +@@ -84,24 +90,23 @@ static int si2157_init(struct dvb_frontend *fe) + struct si2157_cmd cmd; + const struct firmware *fw; + const char *fw_name; +- unsigned int uitmp, chip_id; ++ unsigned int chip_id, xtal_trim; + + dev_dbg(&client->dev, "\n"); + +- /* Returned IF frequency is garbage when firmware is not running */ +- memcpy(cmd.args, "\x15\x00\x06\x07", 4); ++ /* Try to get Xtal trim property, to verify tuner still running */ ++ memcpy(cmd.args, "\x15\x00\x04\x02", 4); + cmd.wlen = 4; + cmd.rlen = 4; + ret = si2157_cmd_execute(client, &cmd); +- if (ret) +- goto err; + +- uitmp = cmd.args[2] << 0 | cmd.args[3] << 8; +- dev_dbg(&client->dev, "if_frequency kHz=%u\n", uitmp); ++ xtal_trim = cmd.args[2] | (cmd.args[3] << 8); + +- if (uitmp == dev->if_frequency / 1000) ++ if ((ret == 0) && (xtal_trim < 16)) + goto warm; + ++ dev->if_frequency = 0; /* we no longer know current tuner state */ ++ + /* power up */ + if (dev->chiptype == SI2157_CHIPTYPE_SI2146) { + memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9); +@@ -230,6 +235,28 @@ skip_fw_download: + + dev_info(&client->dev, "firmware version: %c.%c.%d\n", + cmd.args[6], cmd.args[7], cmd.args[8]); ++ ++ /* enable tuner status flags */ ++ memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 1; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 1; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 1; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; + warm: + /* init statistics in order signal app which are supported */ + c->strength.len = 1; +@@ -274,6 +301,84 @@ err: + return ret; + } + ++static int si2157_tune_wait(struct i2c_client *client, u8 is_digital) ++{ ++#define TUN_TIMEOUT 40 ++#define DIG_TIMEOUT 30 ++#define ANALOG_TIMEOUT 150 ++ struct si2157_dev *dev = i2c_get_clientdata(client); ++ int ret; ++ unsigned long timeout; ++ unsigned long start_time; ++ u8 wait_status; ++ u8 tune_lock_mask; ++ ++ if (is_digital) ++ tune_lock_mask = 0x04; ++ else ++ tune_lock_mask = 0x02; ++ ++ mutex_lock(&dev->i2c_mutex); ++ ++ /* wait tuner command complete */ ++ start_time = jiffies; ++ timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT); ++ while (!time_after(jiffies, timeout)) { ++ ret = i2c_master_recv(client, &wait_status, ++ sizeof(wait_status)); ++ if (ret < 0) { ++ goto err_mutex_unlock; ++ } else if (ret != sizeof(wait_status)) { ++ ret = -EREMOTEIO; ++ goto err_mutex_unlock; ++ } ++ ++ /* tuner done? */ ++ if ((wait_status & 0x81) == 0x81) ++ break; ++ usleep_range(5000, 10000); ++ } ++ /* if we tuned ok, wait a bit for tuner lock */ ++ if ((wait_status & 0x81) == 0x81) { ++ if (is_digital) ++ timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT); ++ else ++ timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT); ++ while (!time_after(jiffies, timeout)) { ++ ret = i2c_master_recv(client, &wait_status, ++ sizeof(wait_status)); ++ if (ret < 0) { ++ goto err_mutex_unlock; ++ } else if (ret != sizeof(wait_status)) { ++ ret = -EREMOTEIO; ++ goto err_mutex_unlock; ++ } ++ ++ /* tuner locked? */ ++ if (wait_status & tune_lock_mask) ++ break; ++ usleep_range(5000, 10000); ++ } ++ } ++ ++ dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n", ++ jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time), ++ wait_status); ++ ++ if ((wait_status & 0xc0) != 0x80) { ++ ret = -ETIMEDOUT; ++ goto err_mutex_unlock; ++ } ++ ++ mutex_unlock(&dev->i2c_mutex); ++ return 0; ++ ++err_mutex_unlock: ++ mutex_unlock(&dev->i2c_mutex); ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ + static int si2157_set_params(struct dvb_frontend *fe) + { + struct i2c_client *client = fe->tuner_priv; +@@ -344,7 +449,7 @@ static int si2157_set_params(struct dvb_frontend *fe) + if (ret) + goto err; + +- /* set if frequency if needed */ ++ /* set digital if frequency if needed */ + if (if_frequency != dev->if_frequency) { + memcpy(cmd.args, "\x14\x00\x06\x07", 4); + cmd.args[4] = (if_frequency / 1000) & 0xff; +@@ -358,7 +463,7 @@ static int si2157_set_params(struct dvb_frontend *fe) + dev->if_frequency = if_frequency; + } + +- /* set frequency */ ++ /* set digital frequency */ + memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8); + cmd.args[4] = (c->frequency >> 0) & 0xff; + cmd.args[5] = (c->frequency >> 8) & 0xff; +@@ -370,19 +475,293 @@ static int si2157_set_params(struct dvb_frontend *fe) + if (ret) + goto err; + ++ dev->bandwidth = bandwidth; ++ dev->frequency = c->frequency; ++ ++ si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */ ++ + return 0; + err: ++ dev->bandwidth = 0; ++ dev->frequency = 0; ++ dev->if_frequency = 0; + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; + } + ++static int si2157_set_analog_params(struct dvb_frontend *fe, ++ struct analog_parameters *params) ++{ ++ struct i2c_client *client = fe->tuner_priv; ++ struct si2157_dev *dev = i2c_get_clientdata(client); ++ char *std; /* for debugging */ ++ int ret; ++ struct si2157_cmd cmd; ++ u32 bandwidth = 0; ++ u32 if_frequency = 0; ++ u32 freq = 0; ++ u64 tmp_lval = 0; ++ u8 system = 0; ++ u8 color = 0; /* 0=NTSC/PAL, 0x10=SECAM */ ++ u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */ ++ ++ if (dev->chiptype != SI2157_CHIPTYPE_SI2157) { ++ dev_info(&client->dev, "%s: Analog tuning not supported for chiptype=%u\n", ++ __func__, dev->chiptype); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ if (!dev->active) ++ si2157_init(fe); ++ ++ if (!dev->active) { ++ ret = -EAGAIN; ++ goto err; ++ } ++ if (params->mode == V4L2_TUNER_RADIO) { ++ /* ++ * std = "fm"; ++ * bandwidth = 1700000; //best can do for FM, AGC will be a mess though ++ * if_frequency = 1250000; //HVR-225x(saa7164), HVR-12xx(cx23885) ++ * if_frequency = 6600000; //HVR-9xx(cx231xx) ++ * if_frequency = 5500000; //HVR-19xx(pvrusb2) ++ */ ++ dev_dbg(&client->dev, "si2157 does not currently support FM radio\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ tmp_lval = params->frequency * 625LL; ++ do_div(tmp_lval, 10); /* convert to HZ */ ++ freq = (u32)tmp_lval; ++ ++ if (freq < 1000000) /* is freq in KHz */ ++ freq = freq * 1000; ++ dev->frequency = freq; ++ ++ /* if_frequency values based on tda187271C2 */ ++ if (params->std & (V4L2_STD_B|V4L2_STD_GH)) { ++ if (freq >= 470000000) { ++ std = "palGH"; ++ bandwidth = 8000000; ++ if_frequency = 6000000; ++ system = 1; ++ if (params->std & (V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)) { ++ std = "secamGH"; ++ color = 0x10; ++ } ++ } else { ++ std = "palB"; ++ bandwidth = 7000000; ++ if_frequency = 6000000; ++ system = 0; ++ if (params->std & V4L2_STD_SECAM_B) { ++ std = "secamB"; ++ color = 0x10; ++ } ++ } ++ } else if (params->std & V4L2_STD_MN) { ++ std = "MN"; ++ bandwidth = 6000000; ++ if_frequency = 5400000; ++ system = 2; ++ } else if (params->std & V4L2_STD_PAL_I) { ++ std = "palI"; ++ bandwidth = 8000000; ++ if_frequency = 7250000; /* TODO: does not work yet */ ++ system = 4; ++ } else if (params->std & V4L2_STD_DK) { ++ std = "palDK"; ++ bandwidth = 8000000; ++ if_frequency = 6900000; /* TODO: does not work yet */ ++ system = 5; ++ if (params->std & V4L2_STD_SECAM_DK) { ++ std = "secamDK"; ++ color = 0x10; ++ } ++ } else if (params->std & V4L2_STD_SECAM_L) { ++ std = "secamL"; ++ bandwidth = 8000000; ++ if_frequency = 6750000; /* TODO: untested */ ++ system = 6; ++ color = 0x10; ++ } else if (params->std & V4L2_STD_SECAM_LC) { ++ std = "secamL'"; ++ bandwidth = 7000000; ++ if_frequency = 1250000; /* TODO: untested */ ++ system = 7; ++ color = 0x10; ++ } else { ++ std = "unknown"; ++ } ++ /* calc channel center freq */ ++ freq = freq - 1250000 + (bandwidth/2); ++ ++ dev_dbg(&client->dev, ++ "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n", ++ params->mode, system, std, params->frequency, ++ freq, if_frequency, bandwidth); ++ ++ /* set analog IF port */ ++ memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6); ++ /* in using dev->if_port, we assume analog and digital IF's */ ++ /* are always on different ports */ ++ /* assumes if_port definition is 0 or 1 for digital out */ ++ cmd.args[4] = (dev->if_port == 1)?8:10; ++ cmd.args[5] = (dev->if_port == 1)?2:1; /* Analog AGC assumed external */ ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* set analog IF output config */ ++ memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* make this distinct from a digital IF */ ++ dev->if_frequency = if_frequency | 1; ++ ++ /* calc and set tuner analog if center frequency */ ++ if_frequency = if_frequency + 1250000 - (bandwidth/2); ++ dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency); ++ ++ memcpy(cmd.args, "\x14\x00\x0C\x06", 4); ++ cmd.args[4] = (if_frequency / 1000) & 0xff; ++ cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff; ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* set analog AGC config */ ++ memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6); ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* set analog video mode */ ++ memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6); ++ cmd.args[4] = system | color; ++#if 1 /* can use dev->inversion if assumed it applies to both digital/analog */ ++ if (invert_analog) ++ cmd.args[5] |= 0x02; ++#else ++ if (dev->inversion) ++ cmd.args[5] |= 0x02; ++#endif ++ cmd.wlen = 6; ++ cmd.rlen = 1; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ /* set analog frequency */ ++ memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8); ++ cmd.args[4] = (freq >> 0) & 0xff; ++ cmd.args[5] = (freq >> 8) & 0xff; ++ cmd.args[6] = (freq >> 16) & 0xff; ++ cmd.args[7] = (freq >> 24) & 0xff; ++ cmd.wlen = 8; ++ cmd.rlen = 1; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++#if 1 /* testing */ ++ /* get tuner status, RSSI values */ ++ memcpy(cmd.args, "\x42\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 12; ++ ret = si2157_cmd_execute(client, &cmd); ++ ++ dev_info(&client->dev, "%s: tuner status: ret=%d rssi=%d mode=%x freq=%d\n", ++ __func__, ret, cmd.args[3], cmd.args[8], ++ (cmd.args[7]<<24 | cmd.args[6]<<16 | ++ cmd.args[5]<<8 | cmd.args[4])); ++#endif ++ dev->bandwidth = bandwidth; ++ ++ si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */ ++ ++ return 0; ++err: ++ dev->bandwidth = 0; ++ dev->frequency = 0; ++ dev->if_frequency = 0; ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; ++} ++ ++static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct i2c_client *client = fe->tuner_priv; ++ struct si2157_dev *dev = i2c_get_clientdata(client); ++ ++ *frequency = dev->frequency; ++ dev_info(&client->dev, "%s: freq=%u\n", __func__, dev->frequency); ++ return 0; ++} ++ ++static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ struct i2c_client *client = fe->tuner_priv; ++ struct si2157_dev *dev = i2c_get_clientdata(client); ++ ++ *bandwidth = dev->bandwidth; ++ dev_info(&client->dev, "%s: bandwidth=%u\n", __func__, dev->bandwidth); ++ return 0; ++} ++ + static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) + { + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); + +- *frequency = dev->if_frequency; ++ *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */ ++ dev_info(&client->dev, "%s: if_frequency=%u\n", __func__, *frequency); ++ return 0; ++} ++ ++static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi) ++{ ++ struct i2c_client *client = fe->tuner_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct si2157_cmd cmd; ++ int ret; ++ int strength; ++ ++ dev_dbg(&client->dev, "\n"); ++ ++ memcpy(cmd.args, "\x42\x00", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 12; ++ ret = si2157_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ ++ c->strength.stat[0].scale = FE_SCALE_DECIBEL; ++ c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000; ++ ++ strength = (s8)cmd.args[3]; ++ strength = (strength > -80) ? (u16)(strength + 100) : 0; ++ strength = strength > 80 ? 100 : strength; ++ ++ *rssi = (u16)(strength * 0xffff / 100); ++ dev_dbg(&client->dev, "%s: strength=%d rssi=%u\n", ++ __func__, (s8)cmd.args[3], *rssi); ++ + return 0; ++err: ++ dev_dbg(&client->dev, "failed=%d\n", ret); ++ return ret; + } + + static const struct dvb_tuner_ops si2157_ops = { +@@ -395,7 +774,12 @@ static const struct dvb_tuner_ops si2157_ops = { + .init = si2157_init, + .sleep = si2157_sleep, + .set_params = si2157_set_params, +- .get_if_frequency = si2157_get_if_frequency, ++ .set_analog_params = si2157_set_analog_params, ++ .get_frequency = si2157_get_frequency, ++ .get_bandwidth = si2157_get_bandwidth, ++ .get_if_frequency = si2157_get_if_frequency, ++ ++ .get_rf_strength = si2157_get_rf_strength, + }; + + static void si2157_stat_work(struct work_struct *work) +@@ -455,7 +839,7 @@ static int si2157_probe(struct i2c_client *client, + cmd.wlen = 0; + cmd.rlen = 1; + ret = si2157_cmd_execute(client, &cmd); +- if (ret) ++ if (ret && (ret != -EAGAIN)) + goto err_kfree; + + memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); +diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h +index e6436f7..2a67c1b 100644 +--- a/drivers/media/tuners/si2157_priv.h ++++ b/drivers/media/tuners/si2157_priv.h +@@ -30,6 +30,8 @@ struct si2157_dev { + u8 chiptype; + u8 if_port; + u32 if_frequency; ++ u32 bandwidth; ++ u32 frequency; + struct delayed_work stat_work; + + #if defined(CONFIG_MEDIA_CONTROLLER) +diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c +index fdd3c22..25aa7bb 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c ++++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c +@@ -599,14 +599,27 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) + return status; + } + } +- if (dev->tuner_type == TUNER_NXP_TDA18271) ++ switch (dev->model) { /* i2c device tuners */ ++ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: ++ case CX231XX_BOARD_HAUPPAUGE_935C: ++ case CX231XX_BOARD_HAUPPAUGE_955Q: ++ case CX231XX_BOARD_HAUPPAUGE_975: ++ case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: + status = cx231xx_set_decoder_video_input(dev, + CX231XX_VMUX_TELEVISION, + INPUT(input)->vmux); +- else +- status = cx231xx_set_decoder_video_input(dev, ++ break; ++ default: ++ if (dev->tuner_type == TUNER_NXP_TDA18271) ++ status = cx231xx_set_decoder_video_input(dev, ++ CX231XX_VMUX_TELEVISION, ++ INPUT(input)->vmux); ++ else ++ status = cx231xx_set_decoder_video_input(dev, + CX231XX_VMUX_COMPOSITE1, + INPUT(input)->vmux); ++ break; ++ }; + + break; + default: +@@ -1205,12 +1218,22 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, + cx231xx_set_field(FLD_SIF_EN, 0)); + break; + default: ++ switch (dev->model) { /* i2c device tuners */ ++ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: ++ case CX231XX_BOARD_HAUPPAUGE_935C: ++ case CX231XX_BOARD_HAUPPAUGE_955Q: ++ case CX231XX_BOARD_HAUPPAUGE_975: ++ case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: ++ /* TODO: Normal mode: SIF passthrough at 14.32 MHz ??? */ ++ break; ++ default: + /* This is just a casual suggestion to people adding + new boards in case they use a tuner type we don't + currently know about */ +- dev_info(dev->dev, +- "Unknown tuner type configuring SIF"); +- break; ++ dev_info(dev->dev, ++ "Unknown tuner type configuring SIF"); ++ break; ++ } + } + break; + +diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c +index f7fcd73..c09b6d7 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-video.c ++++ b/drivers/media/usb/cx231xx/cx231xx-video.c +@@ -1293,7 +1293,7 @@ int cx231xx_s_frequency(struct file *file, void *priv, + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + struct v4l2_frequency new_freq = *f; +- int rc; ++ int rc, need_if_freq = 0; + u32 if_frequency = 5400000; + + dev_dbg(dev->dev, +@@ -1310,14 +1310,30 @@ int cx231xx_s_frequency(struct file *file, void *priv, + /* set pre channel change settings in DIF first */ + rc = cx231xx_tuner_pre_channel_change(dev); + +- call_all(dev, tuner, s_frequency, f); +- call_all(dev, tuner, g_frequency, &new_freq); +- dev->ctl_freq = new_freq.frequency; ++ switch (dev->model) { /* i2c device tuners */ ++ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: ++ case CX231XX_BOARD_HAUPPAUGE_935C: ++ case CX231XX_BOARD_HAUPPAUGE_955Q: ++ case CX231XX_BOARD_HAUPPAUGE_975: ++ case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: ++ if (dev->cx231xx_set_analog_freq) ++ dev->cx231xx_set_analog_freq(dev, f->frequency); ++ dev->ctl_freq = f->frequency; ++ need_if_freq = 1; ++ break; ++ default: ++ call_all(dev, tuner, s_frequency, f); ++ call_all(dev, tuner, g_frequency, &new_freq); ++ dev->ctl_freq = new_freq.frequency; ++ break; ++ } ++ ++ pr_err("%s() %u : %u\n", __func__, f->frequency, dev->ctl_freq); + + /* set post channel change settings in DIF first */ + rc = cx231xx_tuner_post_channel_change(dev); + +- if (dev->tuner_type == TUNER_NXP_TDA18271) { ++ if (need_if_freq || dev->tuner_type == TUNER_NXP_TDA18271) { + if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443)) + if_frequency = 5400000; /*5.4MHz */ + else if (dev->norm & V4L2_STD_B) +@@ -1566,8 +1582,19 @@ int cx231xx_querycap(struct file *file, void *priv, + else + cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; + } +- if (dev->tuner_type != TUNER_ABSENT) ++ switch (dev->model) { /* i2c device tuners */ ++ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: ++ case CX231XX_BOARD_HAUPPAUGE_935C: ++ case CX231XX_BOARD_HAUPPAUGE_955Q: ++ case CX231XX_BOARD_HAUPPAUGE_975: ++ case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: + cap->device_caps |= V4L2_CAP_TUNER; ++ break; ++ default: ++ if (dev->tuner_type != TUNER_ABSENT) ++ cap->device_caps |= V4L2_CAP_TUNER; ++ break; ++ } + cap->capabilities = cap->device_caps | V4L2_CAP_READWRITE | + V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; +@@ -2172,10 +2199,20 @@ static void cx231xx_vdev_init(struct cx231xx *dev, + + video_set_drvdata(vfd, dev); + if (dev->tuner_type == TUNER_ABSENT) { +- v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); +- v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY); +- v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); +- v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); ++ switch (dev->model) { ++ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: ++ case CX231XX_BOARD_HAUPPAUGE_935C: ++ case CX231XX_BOARD_HAUPPAUGE_955Q: ++ case CX231XX_BOARD_HAUPPAUGE_975: ++ case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD: ++ break; ++ default: ++ v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); ++ v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY); ++ v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); ++ v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); ++ break; ++ } + } + } + +-- +2.17.1 + diff --git a/packages/linux-driver-addons/dvb/hauppauge/changelog.txt b/packages/linux-driver-addons/dvb/dvb-latest/changelog.txt similarity index 100% rename from packages/linux-driver-addons/dvb/hauppauge/changelog.txt rename to packages/linux-driver-addons/dvb/dvb-latest/changelog.txt diff --git a/packages/linux-driver-addons/dvb/dvb-latest/icon/icon.png b/packages/linux-driver-addons/dvb/dvb-latest/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..85e5ed9f32a353777a2d1269840783df890c2180 GIT binary patch literal 36366 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 literal 0 HcmV?d00001 diff --git a/packages/linux-driver-addons/dvb/dvb-latest/package.mk b/packages/linux-driver-addons/dvb/dvb-latest/package.mk new file mode 100644 index 0000000000..6336eb4601 --- /dev/null +++ b/packages/linux-driver-addons/dvb/dvb-latest/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dvb-latest" +PKG_VERSION="baf45935ffad914f33faf751ad9f4d0dd276c021" +PKG_SHA256="591f0c4c039f4b2453982187447232fa2e72a48dfd915ed307ae11c7a6427031" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://git.linuxtv.org/media_build.git" +PKG_URL="https://git.linuxtv.org/media_build.git/snapshot/${PKG_VERSION}.tar.gz" +PKG_SOURCE_DIR="${PKG_VERSION}" +PKG_DEPENDS_TARGET="toolchain linux media_tree" +PKG_NEED_UNPACK="$LINUX_DEPENDS media_tree" +PKG_SECTION="driver.dvb" +PKG_LONGDESC="DVB drivers from the latest kernel (media_build)" + +PKG_IS_ADDON="embedded" +PKG_IS_KERNEL_PKG="yes" +PKG_ADDON_IS_STANDALONE="yes" +PKG_ADDON_NAME="DVB drivers from the latest kernel" +PKG_ADDON_TYPE="xbmc.service" +PKG_ADDON_VERSION="${ADDON_VERSION}.${PKG_REV}" + +pre_make_target() { + export KERNEL_VER=$(get_module_dir) + export LDFLAGS="" +} + +make_target() { + cp -RP $(get_build_dir media_tree)/* $PKG_BUILD/linux + + # make staging config (all + experimental) + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) stagingconfig + + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) +} + +makeinstall_target() { + install_driver_addon_files "$PKG_BUILD/v4l/" +} diff --git a/packages/linux-driver-addons/dvb/hauppauge/patches/driver.dvb.hauppauge-01-remove-rmmod.pl.patch b/packages/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch similarity index 100% rename from packages/linux-driver-addons/dvb/hauppauge/patches/driver.dvb.hauppauge-01-remove-rmmod.pl.patch rename to packages/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch diff --git a/packages/linux-driver-addons/dvb/hauppauge/source/default.py b/packages/linux-driver-addons/dvb/dvb-latest/source/default.py similarity index 100% rename from packages/linux-driver-addons/dvb/hauppauge/source/default.py rename to packages/linux-driver-addons/dvb/dvb-latest/source/default.py diff --git a/packages/linux-driver-addons/dvb/hauppauge/icon/icon.png b/packages/linux-driver-addons/dvb/hauppauge/icon/icon.png deleted file mode 100644 index 962157e96e76474e14170551b8bef0ca8607de2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23076 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%0DSdYn5%nglyP2bEUWPY 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 diff --git a/projects/Generic/options b/projects/Generic/options index b1d76b6c64..dc2086850f 100644 --- a/projects/Generic/options +++ b/projects/Generic/options @@ -97,4 +97,4 @@ # driver addons to install: # for a list of additional drivers see packages/linux-driver-addons # Space separated list is supported, - DRIVER_ADDONS="crazycat digital_devices" + DRIVER_ADDONS="crazycat digital_devices dvb-latest"