diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-21 12:03:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-21 12:03:10 -0400 |
commit | c720f5655df159a630fa0290a0bd67c93e92b0bf (patch) | |
tree | 940d139d0ec1ff5201efddef6cc663166a8a2df3 /drivers/media/dvb | |
parent | 33e6c1a0de818d3698cdab27c42915661011319d (diff) | |
parent | 84d6ae431f315e8973aac3c3fe1d550fc9240ef3 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (222 commits)
V4L/DVB (13033): pt1: Don't use a deprecated DMA_BIT_MASK macro
V4L/DVB (13029): radio-si4713: remove #include <linux/version.h>
V4L/DVB (13027): go7007: convert printks to v4l2_info
V4L/DVB (13026): s2250-board: Implement brightness and contrast controls
V4L/DVB (13025): s2250-board: Fix memory leaks
V4L/DVB (13024): go7007: Implement vidioc_g_std and vidioc_querystd
V4L/DVB (13023): go7007: Merge struct gofh and go declarations
V4L/DVB (13022): go7007: Fix mpeg controls
V4L/DVB (13021): go7007: Fix whitespace and line lengths
V4L/DVB (13020): go7007: Updates to Kconfig and Makefile
V4L/DVB (13019): video: initial support for ADV7180
V4L/DVB (13018): kzalloc failure ignored in au8522_probe()
V4L/DVB (13017): gspca: kmalloc failure ignored in sd_start()
V4L/DVB (13016): kmalloc failure ignored in lgdt3304_attach() and s921_attach()
V4L/DVB (13015): kmalloc failure ignored in m920x_firmware_download()
V4L/DVB (13014): Add support for Compro VideoMate E800 (DVB-T part only)
V4L/DVB (13013): FM TX: si4713: Kconfig: Fixed two typos.
V4L/DVB (13012): uvc: introduce missing kfree
V4L/DVB (13011): Change tuner type of BeholdTV cards
V4L/DVB (13009): gspca - stv06xx-hdcs: Reduce exposure range
...
Diffstat (limited to 'drivers/media/dvb')
34 files changed, 7151 insertions, 434 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 1d0e4b1ef10c..35d0817126e9 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
@@ -68,6 +68,10 @@ comment "Supported FireWire (IEEE 1394) Adapters" | |||
68 | depends on DVB_CORE && IEEE1394 | 68 | depends on DVB_CORE && IEEE1394 |
69 | source "drivers/media/dvb/firewire/Kconfig" | 69 | source "drivers/media/dvb/firewire/Kconfig" |
70 | 70 | ||
71 | comment "Supported Earthsoft PT1 Adapters" | ||
72 | depends on DVB_CORE && PCI && I2C | ||
73 | source "drivers/media/dvb/pt1/Kconfig" | ||
74 | |||
71 | comment "Supported DVB Frontends" | 75 | comment "Supported DVB Frontends" |
72 | depends on DVB_CORE | 76 | depends on DVB_CORE |
73 | source "drivers/media/dvb/frontends/Kconfig" | 77 | source "drivers/media/dvb/frontends/Kconfig" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 6092a5bb5a7d..16d262ddb45d 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
@@ -2,6 +2,6 @@ | |||
2 | # Makefile for the kernel multimedia device drivers. | 2 | # Makefile for the kernel multimedia device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ | 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ pt1/ |
6 | 6 | ||
7 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ | 7 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index d13ebcb0c6b6..ddf639ed2fd8 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -850,6 +850,49 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | |||
850 | return 0; | 850 | return 0; |
851 | } | 851 | } |
852 | 852 | ||
853 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | ||
854 | { | ||
855 | int i; | ||
856 | |||
857 | memset(&(fe->dtv_property_cache), 0, | ||
858 | sizeof(struct dtv_frontend_properties)); | ||
859 | |||
860 | fe->dtv_property_cache.state = DTV_CLEAR; | ||
861 | fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; | ||
862 | fe->dtv_property_cache.inversion = INVERSION_AUTO; | ||
863 | fe->dtv_property_cache.fec_inner = FEC_AUTO; | ||
864 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; | ||
865 | fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO; | ||
866 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; | ||
867 | fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO; | ||
868 | fe->dtv_property_cache.symbol_rate = QAM_AUTO; | ||
869 | fe->dtv_property_cache.code_rate_HP = FEC_AUTO; | ||
870 | fe->dtv_property_cache.code_rate_LP = FEC_AUTO; | ||
871 | |||
872 | fe->dtv_property_cache.isdbt_partial_reception = -1; | ||
873 | fe->dtv_property_cache.isdbt_sb_mode = -1; | ||
874 | fe->dtv_property_cache.isdbt_sb_subchannel = -1; | ||
875 | fe->dtv_property_cache.isdbt_sb_segment_idx = -1; | ||
876 | fe->dtv_property_cache.isdbt_sb_segment_count = -1; | ||
877 | fe->dtv_property_cache.isdbt_layer_enabled = 0x7; | ||
878 | for (i = 0; i < 3; i++) { | ||
879 | fe->dtv_property_cache.layer[i].fec = FEC_AUTO; | ||
880 | fe->dtv_property_cache.layer[i].modulation = QAM_AUTO; | ||
881 | fe->dtv_property_cache.layer[i].interleaving = -1; | ||
882 | fe->dtv_property_cache.layer[i].segment_count = -1; | ||
883 | } | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | #define _DTV_CMD(n, s, b) \ | ||
889 | [n] = { \ | ||
890 | .name = #n, \ | ||
891 | .cmd = n, \ | ||
892 | .set = s,\ | ||
893 | .buffer = b \ | ||
894 | } | ||
895 | |||
853 | static struct dtv_cmds_h dtv_cmds[] = { | 896 | static struct dtv_cmds_h dtv_cmds[] = { |
854 | [DTV_TUNE] = { | 897 | [DTV_TUNE] = { |
855 | .name = "DTV_TUNE", | 898 | .name = "DTV_TUNE", |
@@ -949,6 +992,47 @@ static struct dtv_cmds_h dtv_cmds[] = { | |||
949 | .cmd = DTV_TRANSMISSION_MODE, | 992 | .cmd = DTV_TRANSMISSION_MODE, |
950 | .set = 1, | 993 | .set = 1, |
951 | }, | 994 | }, |
995 | |||
996 | _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), | ||
997 | _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), | ||
998 | _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0), | ||
999 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0), | ||
1000 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0), | ||
1001 | _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0), | ||
1002 | _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0), | ||
1003 | _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0), | ||
1004 | _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0), | ||
1005 | _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0), | ||
1006 | _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0), | ||
1007 | _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0), | ||
1008 | _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0), | ||
1009 | _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0), | ||
1010 | _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0), | ||
1011 | _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0), | ||
1012 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), | ||
1013 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), | ||
1014 | |||
1015 | _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0), | ||
1016 | _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0), | ||
1017 | _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0), | ||
1018 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0), | ||
1019 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0), | ||
1020 | _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0), | ||
1021 | _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0), | ||
1022 | _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0), | ||
1023 | _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0), | ||
1024 | _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0), | ||
1025 | _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0), | ||
1026 | _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0), | ||
1027 | _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0), | ||
1028 | _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0), | ||
1029 | _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0), | ||
1030 | _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0), | ||
1031 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0), | ||
1032 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0), | ||
1033 | |||
1034 | _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), | ||
1035 | |||
952 | /* Get */ | 1036 | /* Get */ |
953 | [DTV_DISEQC_SLAVE_REPLY] = { | 1037 | [DTV_DISEQC_SLAVE_REPLY] = { |
954 | .name = "DTV_DISEQC_SLAVE_REPLY", | 1038 | .name = "DTV_DISEQC_SLAVE_REPLY", |
@@ -956,6 +1040,7 @@ static struct dtv_cmds_h dtv_cmds[] = { | |||
956 | .set = 0, | 1040 | .set = 0, |
957 | .buffer = 1, | 1041 | .buffer = 1, |
958 | }, | 1042 | }, |
1043 | |||
959 | [DTV_API_VERSION] = { | 1044 | [DTV_API_VERSION] = { |
960 | .name = "DTV_API_VERSION", | 1045 | .name = "DTV_API_VERSION", |
961 | .cmd = DTV_API_VERSION, | 1046 | .cmd = DTV_API_VERSION, |
@@ -1165,14 +1250,21 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) | |||
1165 | if(c->delivery_system == SYS_ISDBT) { | 1250 | if(c->delivery_system == SYS_ISDBT) { |
1166 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | 1251 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ |
1167 | p->frequency = c->frequency; | 1252 | p->frequency = c->frequency; |
1168 | p->inversion = INVERSION_AUTO; | 1253 | p->inversion = c->inversion; |
1169 | p->u.ofdm.constellation = QAM_AUTO; | 1254 | p->u.ofdm.constellation = QAM_AUTO; |
1170 | p->u.ofdm.code_rate_HP = FEC_AUTO; | 1255 | p->u.ofdm.code_rate_HP = FEC_AUTO; |
1171 | p->u.ofdm.code_rate_LP = FEC_AUTO; | 1256 | p->u.ofdm.code_rate_LP = FEC_AUTO; |
1172 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1173 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | 1257 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; |
1174 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | 1258 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; |
1175 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; | 1259 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; |
1260 | if (c->bandwidth_hz == 8000000) | ||
1261 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
1262 | else if (c->bandwidth_hz == 7000000) | ||
1263 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1264 | else if (c->bandwidth_hz == 6000000) | ||
1265 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1266 | else | ||
1267 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1176 | } | 1268 | } |
1177 | } | 1269 | } |
1178 | 1270 | ||
@@ -1274,6 +1366,65 @@ static int dtv_property_process_get(struct dvb_frontend *fe, | |||
1274 | case DTV_HIERARCHY: | 1366 | case DTV_HIERARCHY: |
1275 | tvp->u.data = fe->dtv_property_cache.hierarchy; | 1367 | tvp->u.data = fe->dtv_property_cache.hierarchy; |
1276 | break; | 1368 | break; |
1369 | |||
1370 | /* ISDB-T Support here */ | ||
1371 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1372 | tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception; | ||
1373 | break; | ||
1374 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1375 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode; | ||
1376 | break; | ||
1377 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1378 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel; | ||
1379 | break; | ||
1380 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1381 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx; | ||
1382 | break; | ||
1383 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1384 | tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count; | ||
1385 | break; | ||
1386 | case DTV_ISDBT_LAYER_ENABLED: | ||
1387 | tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled; | ||
1388 | break; | ||
1389 | case DTV_ISDBT_LAYERA_FEC: | ||
1390 | tvp->u.data = fe->dtv_property_cache.layer[0].fec; | ||
1391 | break; | ||
1392 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1393 | tvp->u.data = fe->dtv_property_cache.layer[0].modulation; | ||
1394 | break; | ||
1395 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1396 | tvp->u.data = fe->dtv_property_cache.layer[0].segment_count; | ||
1397 | break; | ||
1398 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1399 | tvp->u.data = fe->dtv_property_cache.layer[0].interleaving; | ||
1400 | break; | ||
1401 | case DTV_ISDBT_LAYERB_FEC: | ||
1402 | tvp->u.data = fe->dtv_property_cache.layer[1].fec; | ||
1403 | break; | ||
1404 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1405 | tvp->u.data = fe->dtv_property_cache.layer[1].modulation; | ||
1406 | break; | ||
1407 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1408 | tvp->u.data = fe->dtv_property_cache.layer[1].segment_count; | ||
1409 | break; | ||
1410 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1411 | tvp->u.data = fe->dtv_property_cache.layer[1].interleaving; | ||
1412 | break; | ||
1413 | case DTV_ISDBT_LAYERC_FEC: | ||
1414 | tvp->u.data = fe->dtv_property_cache.layer[2].fec; | ||
1415 | break; | ||
1416 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1417 | tvp->u.data = fe->dtv_property_cache.layer[2].modulation; | ||
1418 | break; | ||
1419 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1420 | tvp->u.data = fe->dtv_property_cache.layer[2].segment_count; | ||
1421 | break; | ||
1422 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1423 | tvp->u.data = fe->dtv_property_cache.layer[2].interleaving; | ||
1424 | break; | ||
1425 | case DTV_ISDBS_TS_ID: | ||
1426 | tvp->u.data = fe->dtv_property_cache.isdbs_ts_id; | ||
1427 | break; | ||
1277 | default: | 1428 | default: |
1278 | r = -1; | 1429 | r = -1; |
1279 | } | 1430 | } |
@@ -1302,10 +1453,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1302 | /* Reset a cache of data specific to the frontend here. This does | 1453 | /* Reset a cache of data specific to the frontend here. This does |
1303 | * not effect hardware. | 1454 | * not effect hardware. |
1304 | */ | 1455 | */ |
1456 | dvb_frontend_clear_cache(fe); | ||
1305 | dprintk("%s() Flushing property cache\n", __func__); | 1457 | dprintk("%s() Flushing property cache\n", __func__); |
1306 | memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); | ||
1307 | fe->dtv_property_cache.state = tvp->cmd; | ||
1308 | fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; | ||
1309 | break; | 1458 | break; |
1310 | case DTV_TUNE: | 1459 | case DTV_TUNE: |
1311 | /* interpret the cache of data, build either a traditional frontend | 1460 | /* interpret the cache of data, build either a traditional frontend |
@@ -1371,6 +1520,65 @@ static int dtv_property_process_set(struct dvb_frontend *fe, | |||
1371 | case DTV_HIERARCHY: | 1520 | case DTV_HIERARCHY: |
1372 | fe->dtv_property_cache.hierarchy = tvp->u.data; | 1521 | fe->dtv_property_cache.hierarchy = tvp->u.data; |
1373 | break; | 1522 | break; |
1523 | |||
1524 | /* ISDB-T Support here */ | ||
1525 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1526 | fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data; | ||
1527 | break; | ||
1528 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1529 | fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data; | ||
1530 | break; | ||
1531 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1532 | fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data; | ||
1533 | break; | ||
1534 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1535 | fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data; | ||
1536 | break; | ||
1537 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1538 | fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data; | ||
1539 | break; | ||
1540 | case DTV_ISDBT_LAYER_ENABLED: | ||
1541 | fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data; | ||
1542 | break; | ||
1543 | case DTV_ISDBT_LAYERA_FEC: | ||
1544 | fe->dtv_property_cache.layer[0].fec = tvp->u.data; | ||
1545 | break; | ||
1546 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1547 | fe->dtv_property_cache.layer[0].modulation = tvp->u.data; | ||
1548 | break; | ||
1549 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1550 | fe->dtv_property_cache.layer[0].segment_count = tvp->u.data; | ||
1551 | break; | ||
1552 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1553 | fe->dtv_property_cache.layer[0].interleaving = tvp->u.data; | ||
1554 | break; | ||
1555 | case DTV_ISDBT_LAYERB_FEC: | ||
1556 | fe->dtv_property_cache.layer[1].fec = tvp->u.data; | ||
1557 | break; | ||
1558 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1559 | fe->dtv_property_cache.layer[1].modulation = tvp->u.data; | ||
1560 | break; | ||
1561 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1562 | fe->dtv_property_cache.layer[1].segment_count = tvp->u.data; | ||
1563 | break; | ||
1564 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1565 | fe->dtv_property_cache.layer[1].interleaving = tvp->u.data; | ||
1566 | break; | ||
1567 | case DTV_ISDBT_LAYERC_FEC: | ||
1568 | fe->dtv_property_cache.layer[2].fec = tvp->u.data; | ||
1569 | break; | ||
1570 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1571 | fe->dtv_property_cache.layer[2].modulation = tvp->u.data; | ||
1572 | break; | ||
1573 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1574 | fe->dtv_property_cache.layer[2].segment_count = tvp->u.data; | ||
1575 | break; | ||
1576 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1577 | fe->dtv_property_cache.layer[2].interleaving = tvp->u.data; | ||
1578 | break; | ||
1579 | case DTV_ISDBS_TS_ID: | ||
1580 | fe->dtv_property_cache.isdbs_ts_id = tvp->u.data; | ||
1581 | break; | ||
1374 | default: | 1582 | default: |
1375 | r = -1; | 1583 | r = -1; |
1376 | } | 1584 | } |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index e176da472d7a..810f07d63246 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
@@ -341,6 +341,23 @@ struct dtv_frontend_properties { | |||
341 | fe_rolloff_t rolloff; | 341 | fe_rolloff_t rolloff; |
342 | 342 | ||
343 | fe_delivery_system_t delivery_system; | 343 | fe_delivery_system_t delivery_system; |
344 | |||
345 | /* ISDB-T specifics */ | ||
346 | u8 isdbt_partial_reception; | ||
347 | u8 isdbt_sb_mode; | ||
348 | u8 isdbt_sb_subchannel; | ||
349 | u32 isdbt_sb_segment_idx; | ||
350 | u32 isdbt_sb_segment_count; | ||
351 | u8 isdbt_layer_enabled; | ||
352 | struct { | ||
353 | u8 segment_count; | ||
354 | fe_code_rate_t fec; | ||
355 | fe_modulation_t modulation; | ||
356 | u8 interleaving; | ||
357 | } layer[3]; | ||
358 | |||
359 | /* ISDB-T specifics */ | ||
360 | u32 isdbs_ts_id; | ||
344 | }; | 361 | }; |
345 | 362 | ||
346 | struct dvb_frontend { | 363 | struct dvb_frontend { |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 8b8bc04ee980..0e4b97fba384 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -71,6 +71,7 @@ config DVB_USB_DIB0700 | |||
71 | depends on DVB_USB | 71 | depends on DVB_USB |
72 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | 72 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE |
73 | select DVB_DIB7000M if !DVB_FE_CUSTOMISE | 73 | select DVB_DIB7000M if !DVB_FE_CUSTOMISE |
74 | select DVB_DIB8000 if !DVB_FE_CUSTOMISE | ||
74 | select DVB_DIB3000MC if !DVB_FE_CUSTOMISE | 75 | select DVB_DIB3000MC if !DVB_FE_CUSTOMISE |
75 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 76 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
76 | select DVB_LGDT3305 if !DVB_FE_CUSTOMISE | 77 | select DVB_LGDT3305 if !DVB_FE_CUSTOMISE |
@@ -87,7 +88,7 @@ config DVB_USB_DIB0700 | |||
87 | Avermedia and other big and small companies. | 88 | Avermedia and other big and small companies. |
88 | 89 | ||
89 | For an up-to-date list of devices supported by this driver, have a look | 90 | For an up-to-date list of devices supported by this driver, have a look |
90 | on the Linux-DVB Wiki at www.linuxtv.org. | 91 | on the LinuxTV Wiki at www.linuxtv.org. |
91 | 92 | ||
92 | Say Y if you own such a device and want to use it. You should build it as | 93 | Say Y if you own such a device and want to use it. You should build it as |
93 | a module. | 94 | a module. |
@@ -315,3 +316,9 @@ config DVB_USB_CE6230 | |||
315 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | 316 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE |
316 | help | 317 | help |
317 | Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver | 318 | Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver |
319 | |||
320 | config DVB_USB_FRIIO | ||
321 | tristate "Friio ISDB-T USB2.0 Receiver support" | ||
322 | depends on DVB_USB | ||
323 | help | ||
324 | Say Y here to support the Japanese DTV receiver Friio. | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index f92734ed777a..85b83a43d55d 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -79,6 +79,9 @@ obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o | |||
79 | dvb-usb-ce6230-objs = ce6230.o | 79 | dvb-usb-ce6230-objs = ce6230.o |
80 | obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o | 80 | obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o |
81 | 81 | ||
82 | dvb-usb-friio-objs = friio.o friio-fe.o | ||
83 | obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o | ||
84 | |||
82 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 85 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ |
83 | # due to tuner-xc3028 | 86 | # due to tuner-xc3028 |
84 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 87 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 99cdd0d101ca..cf042b309b46 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
@@ -61,10 +61,13 @@ static struct af9013_config af9015_af9013_config[] = { | |||
61 | 61 | ||
62 | static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | 62 | static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) |
63 | { | 63 | { |
64 | #define BUF_LEN 63 | ||
65 | #define REQ_HDR_LEN 8 /* send header size */ | ||
66 | #define ACK_HDR_LEN 2 /* rece header size */ | ||
64 | int act_len, ret; | 67 | int act_len, ret; |
65 | u8 buf[64]; | 68 | u8 buf[BUF_LEN]; |
66 | u8 write = 1; | 69 | u8 write = 1; |
67 | u8 msg_len = 8; | 70 | u8 msg_len = REQ_HDR_LEN; |
68 | static u8 seq; /* packet sequence number */ | 71 | static u8 seq; /* packet sequence number */ |
69 | 72 | ||
70 | if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) | 73 | if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) |
@@ -94,7 +97,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | |||
94 | break; | 97 | break; |
95 | case WRITE_MEMORY: | 98 | case WRITE_MEMORY: |
96 | if (((req->addr & 0xff00) == 0xff00) || | 99 | if (((req->addr & 0xff00) == 0xff00) || |
97 | ((req->addr & 0xae00) == 0xae00)) | 100 | ((req->addr & 0xff00) == 0xae00)) |
98 | buf[0] = WRITE_VIRTUAL_MEMORY; | 101 | buf[0] = WRITE_VIRTUAL_MEMORY; |
99 | case WRITE_VIRTUAL_MEMORY: | 102 | case WRITE_VIRTUAL_MEMORY: |
100 | case COPY_FIRMWARE: | 103 | case COPY_FIRMWARE: |
@@ -107,17 +110,26 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | |||
107 | goto error_unlock; | 110 | goto error_unlock; |
108 | } | 111 | } |
109 | 112 | ||
113 | /* buffer overflow check */ | ||
114 | if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || | ||
115 | (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { | ||
116 | err("too much data; cmd:%d len:%d", req->cmd, req->data_len); | ||
117 | ret = -EINVAL; | ||
118 | goto error_unlock; | ||
119 | } | ||
120 | |||
110 | /* write requested */ | 121 | /* write requested */ |
111 | if (write) { | 122 | if (write) { |
112 | memcpy(&buf[8], req->data, req->data_len); | 123 | memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); |
113 | msg_len += req->data_len; | 124 | msg_len += req->data_len; |
114 | } | 125 | } |
126 | |||
115 | deb_xfer(">>> "); | 127 | deb_xfer(">>> "); |
116 | debug_dump(buf, msg_len, deb_xfer); | 128 | debug_dump(buf, msg_len, deb_xfer); |
117 | 129 | ||
118 | /* send req */ | 130 | /* send req */ |
119 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, | 131 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, |
120 | &act_len, AF9015_USB_TIMEOUT); | 132 | &act_len, AF9015_USB_TIMEOUT); |
121 | if (ret) | 133 | if (ret) |
122 | err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); | 134 | err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); |
123 | else | 135 | else |
@@ -130,10 +142,14 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | |||
130 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) | 142 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) |
131 | goto exit_unlock; | 143 | goto exit_unlock; |
132 | 144 | ||
133 | /* receive ack and data if read req */ | 145 | /* write receives seq + status = 2 bytes |
134 | msg_len = 1 + 1 + req->data_len; /* seq + status + data len */ | 146 | read receives seq + status + data = 2 + N bytes */ |
147 | msg_len = ACK_HDR_LEN; | ||
148 | if (!write) | ||
149 | msg_len += req->data_len; | ||
150 | |||
135 | ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, | 151 | ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, |
136 | &act_len, AF9015_USB_TIMEOUT); | 152 | &act_len, AF9015_USB_TIMEOUT); |
137 | if (ret) { | 153 | if (ret) { |
138 | err("recv bulk message failed:%d", ret); | 154 | err("recv bulk message failed:%d", ret); |
139 | ret = -1; | 155 | ret = -1; |
@@ -159,7 +175,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | |||
159 | 175 | ||
160 | /* read request, copy returned data to return buf */ | 176 | /* read request, copy returned data to return buf */ |
161 | if (!write) | 177 | if (!write) |
162 | memcpy(req->data, &buf[2], req->data_len); | 178 | memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); |
163 | 179 | ||
164 | error_unlock: | 180 | error_unlock: |
165 | exit_unlock: | 181 | exit_unlock: |
@@ -369,12 +385,14 @@ static int af9015_init_endpoint(struct dvb_usb_device *d) | |||
369 | u8 packet_size; | 385 | u8 packet_size; |
370 | deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); | 386 | deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); |
371 | 387 | ||
388 | /* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0. | ||
389 | We use smaller - about 1/4 from the original, 5 and 87. */ | ||
372 | #define TS_PACKET_SIZE 188 | 390 | #define TS_PACKET_SIZE 188 |
373 | 391 | ||
374 | #define TS_USB20_PACKET_COUNT 348 | 392 | #define TS_USB20_PACKET_COUNT 87 |
375 | #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) | 393 | #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) |
376 | 394 | ||
377 | #define TS_USB11_PACKET_COUNT 21 | 395 | #define TS_USB11_PACKET_COUNT 5 |
378 | #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) | 396 | #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) |
379 | 397 | ||
380 | #define TS_USB20_MAX_PACKET_SIZE 512 | 398 | #define TS_USB20_MAX_PACKET_SIZE 512 |
@@ -868,13 +886,13 @@ static int af9015_read_config(struct usb_device *udev) | |||
868 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ | 886 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ |
869 | if (udev->speed == USB_SPEED_FULL) { | 887 | if (udev->speed == USB_SPEED_FULL) { |
870 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize | 888 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize |
871 | = TS_USB11_MAX_PACKET_SIZE; | 889 | = TS_USB11_FRAME_SIZE; |
872 | /* disable 2nd adapter because we don't have | 890 | /* disable 2nd adapter because we don't have |
873 | PID-filters */ | 891 | PID-filters */ |
874 | af9015_config.dual_mode = 0; | 892 | af9015_config.dual_mode = 0; |
875 | } else { | 893 | } else { |
876 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize | 894 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize |
877 | = TS_USB20_MAX_PACKET_SIZE; | 895 | = TS_USB20_FRAME_SIZE; |
878 | } | 896 | } |
879 | } | 897 | } |
880 | 898 | ||
@@ -1310,7 +1328,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1310 | .u = { | 1328 | .u = { |
1311 | .bulk = { | 1329 | .bulk = { |
1312 | .buffersize = | 1330 | .buffersize = |
1313 | TS_USB20_MAX_PACKET_SIZE, | 1331 | TS_USB20_FRAME_SIZE, |
1314 | } | 1332 | } |
1315 | } | 1333 | } |
1316 | }, | 1334 | }, |
@@ -1416,7 +1434,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1416 | .u = { | 1434 | .u = { |
1417 | .bulk = { | 1435 | .bulk = { |
1418 | .buffersize = | 1436 | .buffersize = |
1419 | TS_USB20_MAX_PACKET_SIZE, | 1437 | TS_USB20_FRAME_SIZE, |
1420 | } | 1438 | } |
1421 | } | 1439 | } |
1422 | }, | 1440 | }, |
@@ -1522,7 +1540,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1522 | .u = { | 1540 | .u = { |
1523 | .bulk = { | 1541 | .bulk = { |
1524 | .buffersize = | 1542 | .buffersize = |
1525 | TS_USB20_MAX_PACKET_SIZE, | 1543 | TS_USB20_FRAME_SIZE, |
1526 | } | 1544 | } |
1527 | } | 1545 | } |
1528 | }, | 1546 | }, |
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 7381aff4dcf6..2ae7f648effe 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
@@ -203,11 +203,11 @@ static struct i2c_algorithm anysee_i2c_algo = { | |||
203 | 203 | ||
204 | static int anysee_mt352_demod_init(struct dvb_frontend *fe) | 204 | static int anysee_mt352_demod_init(struct dvb_frontend *fe) |
205 | { | 205 | { |
206 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | 206 | static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x28 }; |
207 | static u8 reset [] = { RESET, 0x80 }; | 207 | static u8 reset[] = { RESET, 0x80 }; |
208 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | 208 | static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; |
209 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | 209 | static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0x20 }; |
210 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | 210 | static u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; |
211 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | 211 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; |
212 | 212 | ||
213 | mt352_write(fe, clock_config, sizeof(clock_config)); | 213 | mt352_write(fe, clock_config, sizeof(clock_config)); |
@@ -485,7 +485,7 @@ static int anysee_probe(struct usb_interface *intf, | |||
485 | return ret; | 485 | return ret; |
486 | } | 486 | } |
487 | 487 | ||
488 | static struct usb_device_id anysee_table [] = { | 488 | static struct usb_device_id anysee_table[] = { |
489 | { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, | 489 | { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, |
490 | { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, | 490 | { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, |
491 | { } /* Terminating entry */ | 491 | { } /* Terminating entry */ |
@@ -511,7 +511,7 @@ static struct dvb_usb_device_properties anysee_properties = { | |||
511 | .endpoint = 0x82, | 511 | .endpoint = 0x82, |
512 | .u = { | 512 | .u = { |
513 | .bulk = { | 513 | .bulk = { |
514 | .buffersize = 512, | 514 | .buffersize = (16*512), |
515 | } | 515 | } |
516 | } | 516 | } |
517 | }, | 517 | }, |
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c index 52badc00e673..0737c6377892 100644 --- a/drivers/media/dvb/dvb-usb/ce6230.c +++ b/drivers/media/dvb/dvb-usb/ce6230.c | |||
@@ -274,7 +274,7 @@ static struct dvb_usb_device_properties ce6230_properties = { | |||
274 | .endpoint = 0x82, | 274 | .endpoint = 0x82, |
275 | .u = { | 275 | .u = { |
276 | .bulk = { | 276 | .bulk = { |
277 | .buffersize = 512, | 277 | .buffersize = (16*512), |
278 | } | 278 | } |
279 | } | 279 | } |
280 | }, | 280 | }, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index d1d6f4491403..0b2812aa30a4 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -4,13 +4,14 @@ | |||
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
5 | * Software Foundation, version 2. | 5 | * Software Foundation, version 2. |
6 | * | 6 | * |
7 | * Copyright (C) 2005-7 DiBcom, SA | 7 | * Copyright (C) 2005-9 DiBcom, SA et al |
8 | */ | 8 | */ |
9 | #include "dib0700.h" | 9 | #include "dib0700.h" |
10 | 10 | ||
11 | #include "dib3000mc.h" | 11 | #include "dib3000mc.h" |
12 | #include "dib7000m.h" | 12 | #include "dib7000m.h" |
13 | #include "dib7000p.h" | 13 | #include "dib7000p.h" |
14 | #include "dib8000.h" | ||
14 | #include "mt2060.h" | 15 | #include "mt2060.h" |
15 | #include "mt2266.h" | 16 | #include "mt2266.h" |
16 | #include "tuner-xc2028.h" | 17 | #include "tuner-xc2028.h" |
@@ -1098,11 +1099,13 @@ static struct dibx000_agc_config dib7070_agc_config = { | |||
1098 | 1099 | ||
1099 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | 1100 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) |
1100 | { | 1101 | { |
1102 | deb_info("reset: %d", onoff); | ||
1101 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | 1103 | return dib7000p_set_gpio(fe, 8, 0, !onoff); |
1102 | } | 1104 | } |
1103 | 1105 | ||
1104 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | 1106 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) |
1105 | { | 1107 | { |
1108 | deb_info("sleep: %d", onoff); | ||
1106 | return dib7000p_set_gpio(fe, 9, 0, onoff); | 1109 | return dib7000p_set_gpio(fe, 9, 0, onoff); |
1107 | } | 1110 | } |
1108 | 1111 | ||
@@ -1112,16 +1115,26 @@ static struct dib0070_config dib7070p_dib0070_config[2] = { | |||
1112 | .reset = dib7070_tuner_reset, | 1115 | .reset = dib7070_tuner_reset, |
1113 | .sleep = dib7070_tuner_sleep, | 1116 | .sleep = dib7070_tuner_sleep, |
1114 | .clock_khz = 12000, | 1117 | .clock_khz = 12000, |
1115 | .clock_pad_drive = 4 | 1118 | .clock_pad_drive = 4, |
1119 | .charge_pump = 2, | ||
1116 | }, { | 1120 | }, { |
1117 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | 1121 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, |
1118 | .reset = dib7070_tuner_reset, | 1122 | .reset = dib7070_tuner_reset, |
1119 | .sleep = dib7070_tuner_sleep, | 1123 | .sleep = dib7070_tuner_sleep, |
1120 | .clock_khz = 12000, | 1124 | .clock_khz = 12000, |
1121 | 1125 | .charge_pump = 2, | |
1122 | } | 1126 | } |
1123 | }; | 1127 | }; |
1124 | 1128 | ||
1129 | static struct dib0070_config dib7770p_dib0070_config = { | ||
1130 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
1131 | .reset = dib7070_tuner_reset, | ||
1132 | .sleep = dib7070_tuner_sleep, | ||
1133 | .clock_khz = 12000, | ||
1134 | .clock_pad_drive = 0, | ||
1135 | .flip_chip = 1, | ||
1136 | }; | ||
1137 | |||
1125 | static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | 1138 | static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) |
1126 | { | 1139 | { |
1127 | struct dvb_usb_adapter *adap = fe->dvb->priv; | 1140 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
@@ -1139,6 +1152,45 @@ static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_fronte | |||
1139 | return state->set_param_save(fe, fep); | 1152 | return state->set_param_save(fe, fep); |
1140 | } | 1153 | } |
1141 | 1154 | ||
1155 | static int dib7770_set_param_override(struct dvb_frontend *fe, | ||
1156 | struct dvb_frontend_parameters *fep) | ||
1157 | { | ||
1158 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
1159 | struct dib0700_adapter_state *state = adap->priv; | ||
1160 | |||
1161 | u16 offset; | ||
1162 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
1163 | switch (band) { | ||
1164 | case BAND_VHF: | ||
1165 | dib7000p_set_gpio(fe, 0, 0, 1); | ||
1166 | offset = 850; | ||
1167 | break; | ||
1168 | case BAND_UHF: | ||
1169 | default: | ||
1170 | dib7000p_set_gpio(fe, 0, 0, 0); | ||
1171 | offset = 250; | ||
1172 | break; | ||
1173 | } | ||
1174 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); | ||
1175 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
1176 | return state->set_param_save(fe, fep); | ||
1177 | } | ||
1178 | |||
1179 | static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap) | ||
1180 | { | ||
1181 | struct dib0700_adapter_state *st = adap->priv; | ||
1182 | struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, | ||
1183 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
1184 | |||
1185 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
1186 | &dib7770p_dib0070_config) == NULL) | ||
1187 | return -ENODEV; | ||
1188 | |||
1189 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
1190 | adap->fe->ops.tuner_ops.set_params = dib7770_set_param_override; | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1142 | static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) | 1194 | static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) |
1143 | { | 1195 | { |
1144 | struct dib0700_adapter_state *st = adap->priv; | 1196 | struct dib0700_adapter_state *st = adap->priv; |
@@ -1217,6 +1269,306 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) | |||
1217 | return adap->fe == NULL ? -ENODEV : 0; | 1269 | return adap->fe == NULL ? -ENODEV : 0; |
1218 | } | 1270 | } |
1219 | 1271 | ||
1272 | /* DIB807x generic */ | ||
1273 | static struct dibx000_agc_config dib807x_agc_config[2] = { | ||
1274 | { | ||
1275 | BAND_VHF, | ||
1276 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, | ||
1277 | * P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, | ||
1278 | * P_agc_inv_pwm2=0,P_agc_inh_dc_rv_est=0, | ||
1279 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, | ||
1280 | * P_agc_write=0 */ | ||
1281 | (0 << 15) | (0 << 14) | (7 << 11) | (0 << 10) | (0 << 9) | | ||
1282 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | | ||
1283 | (0 << 0), /* setup*/ | ||
1284 | |||
1285 | 600, /* inv_gain*/ | ||
1286 | 10, /* time_stabiliz*/ | ||
1287 | |||
1288 | 0, /* alpha_level*/ | ||
1289 | 118, /* thlock*/ | ||
1290 | |||
1291 | 0, /* wbd_inv*/ | ||
1292 | 3530, /* wbd_ref*/ | ||
1293 | 1, /* wbd_sel*/ | ||
1294 | 5, /* wbd_alpha*/ | ||
1295 | |||
1296 | 65535, /* agc1_max*/ | ||
1297 | 0, /* agc1_min*/ | ||
1298 | |||
1299 | 65535, /* agc2_max*/ | ||
1300 | 0, /* agc2_min*/ | ||
1301 | |||
1302 | 0, /* agc1_pt1*/ | ||
1303 | 40, /* agc1_pt2*/ | ||
1304 | 183, /* agc1_pt3*/ | ||
1305 | 206, /* agc1_slope1*/ | ||
1306 | 255, /* agc1_slope2*/ | ||
1307 | 72, /* agc2_pt1*/ | ||
1308 | 152, /* agc2_pt2*/ | ||
1309 | 88, /* agc2_slope1*/ | ||
1310 | 90, /* agc2_slope2*/ | ||
1311 | |||
1312 | 17, /* alpha_mant*/ | ||
1313 | 27, /* alpha_exp*/ | ||
1314 | 23, /* beta_mant*/ | ||
1315 | 51, /* beta_exp*/ | ||
1316 | |||
1317 | 0, /* perform_agc_softsplit*/ | ||
1318 | }, { | ||
1319 | BAND_UHF, | ||
1320 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, | ||
1321 | * P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, | ||
1322 | * P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
1323 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, | ||
1324 | * P_agc_write=0 */ | ||
1325 | (0 << 15) | (0 << 14) | (1 << 11) | (0 << 10) | (0 << 9) | | ||
1326 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | | ||
1327 | (0 << 0), /* setup */ | ||
1328 | |||
1329 | 600, /* inv_gain*/ | ||
1330 | 10, /* time_stabiliz*/ | ||
1331 | |||
1332 | 0, /* alpha_level*/ | ||
1333 | 118, /* thlock*/ | ||
1334 | |||
1335 | 0, /* wbd_inv*/ | ||
1336 | 3530, /* wbd_ref*/ | ||
1337 | 1, /* wbd_sel*/ | ||
1338 | 5, /* wbd_alpha*/ | ||
1339 | |||
1340 | 65535, /* agc1_max*/ | ||
1341 | 0, /* agc1_min*/ | ||
1342 | |||
1343 | 65535, /* agc2_max*/ | ||
1344 | 0, /* agc2_min*/ | ||
1345 | |||
1346 | 0, /* agc1_pt1*/ | ||
1347 | 40, /* agc1_pt2*/ | ||
1348 | 183, /* agc1_pt3*/ | ||
1349 | 206, /* agc1_slope1*/ | ||
1350 | 255, /* agc1_slope2*/ | ||
1351 | 72, /* agc2_pt1*/ | ||
1352 | 152, /* agc2_pt2*/ | ||
1353 | 88, /* agc2_slope1*/ | ||
1354 | 90, /* agc2_slope2*/ | ||
1355 | |||
1356 | 17, /* alpha_mant*/ | ||
1357 | 27, /* alpha_exp*/ | ||
1358 | 23, /* beta_mant*/ | ||
1359 | 51, /* beta_exp*/ | ||
1360 | |||
1361 | 0, /* perform_agc_softsplit*/ | ||
1362 | } | ||
1363 | }; | ||
1364 | |||
1365 | static struct dibx000_bandwidth_config dib807x_bw_config_12_mhz = { | ||
1366 | 60000, 15000, /* internal, sampling*/ | ||
1367 | 1, 20, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass*/ | ||
1368 | 0, 0, 1, 1, 2, /* misc: refdiv, bypclk_div, IO_CLK_en_core, | ||
1369 | ADClkSrc, modulo */ | ||
1370 | (3 << 14) | (1 << 12) | (599 << 0), /* sad_cfg: refsel, sel, freq_15k*/ | ||
1371 | (0 << 25) | 0, /* ifreq = 0.000000 MHz*/ | ||
1372 | 18179755, /* timf*/ | ||
1373 | 12000000, /* xtal_hz*/ | ||
1374 | }; | ||
1375 | |||
1376 | static struct dib8000_config dib807x_dib8000_config[2] = { | ||
1377 | { | ||
1378 | .output_mpeg2_in_188_bytes = 1, | ||
1379 | |||
1380 | .agc_config_count = 2, | ||
1381 | .agc = dib807x_agc_config, | ||
1382 | .pll = &dib807x_bw_config_12_mhz, | ||
1383 | .tuner_is_baseband = 1, | ||
1384 | |||
1385 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
1386 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
1387 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
1388 | |||
1389 | .hostbus_diversity = 1, | ||
1390 | .div_cfg = 1, | ||
1391 | .agc_control = &dib0070_ctrl_agc_filter, | ||
1392 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
1393 | .drives = 0x2d98, | ||
1394 | }, { | ||
1395 | .output_mpeg2_in_188_bytes = 1, | ||
1396 | |||
1397 | .agc_config_count = 2, | ||
1398 | .agc = dib807x_agc_config, | ||
1399 | .pll = &dib807x_bw_config_12_mhz, | ||
1400 | .tuner_is_baseband = 1, | ||
1401 | |||
1402 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
1403 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
1404 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
1405 | |||
1406 | .hostbus_diversity = 1, | ||
1407 | .agc_control = &dib0070_ctrl_agc_filter, | ||
1408 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
1409 | .drives = 0x2d98, | ||
1410 | } | ||
1411 | }; | ||
1412 | |||
1413 | static int dib807x_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
1414 | { | ||
1415 | return dib8000_set_gpio(fe, 5, 0, !onoff); | ||
1416 | } | ||
1417 | |||
1418 | static int dib807x_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
1419 | { | ||
1420 | return dib8000_set_gpio(fe, 0, 0, onoff); | ||
1421 | } | ||
1422 | |||
1423 | static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = { | ||
1424 | { 240, 7}, | ||
1425 | { 0xffff, 6}, | ||
1426 | }; | ||
1427 | |||
1428 | static struct dib0070_config dib807x_dib0070_config[2] = { | ||
1429 | { | ||
1430 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
1431 | .reset = dib807x_tuner_reset, | ||
1432 | .sleep = dib807x_tuner_sleep, | ||
1433 | .clock_khz = 12000, | ||
1434 | .clock_pad_drive = 4, | ||
1435 | .vga_filter = 1, | ||
1436 | .force_crystal_mode = 1, | ||
1437 | .enable_third_order_filter = 1, | ||
1438 | .charge_pump = 0, | ||
1439 | .wbd_gain = dib8070_wbd_gain_cfg, | ||
1440 | .osc_buffer_state = 0, | ||
1441 | .freq_offset_khz_uhf = -100, | ||
1442 | .freq_offset_khz_vhf = -100, | ||
1443 | }, { | ||
1444 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
1445 | .reset = dib807x_tuner_reset, | ||
1446 | .sleep = dib807x_tuner_sleep, | ||
1447 | .clock_khz = 12000, | ||
1448 | .clock_pad_drive = 2, | ||
1449 | .vga_filter = 1, | ||
1450 | .force_crystal_mode = 1, | ||
1451 | .enable_third_order_filter = 1, | ||
1452 | .charge_pump = 0, | ||
1453 | .wbd_gain = dib8070_wbd_gain_cfg, | ||
1454 | .osc_buffer_state = 0, | ||
1455 | .freq_offset_khz_uhf = -25, | ||
1456 | .freq_offset_khz_vhf = -25, | ||
1457 | } | ||
1458 | }; | ||
1459 | |||
1460 | static int dib807x_set_param_override(struct dvb_frontend *fe, | ||
1461 | struct dvb_frontend_parameters *fep) | ||
1462 | { | ||
1463 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
1464 | struct dib0700_adapter_state *state = adap->priv; | ||
1465 | |||
1466 | u16 offset = dib0070_wbd_offset(fe); | ||
1467 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
1468 | switch (band) { | ||
1469 | case BAND_VHF: | ||
1470 | offset += 750; | ||
1471 | break; | ||
1472 | case BAND_UHF: /* fall-thru wanted */ | ||
1473 | default: | ||
1474 | offset += 250; break; | ||
1475 | } | ||
1476 | deb_info("WBD for DiB8000: %d\n", offset); | ||
1477 | dib8000_set_wbd_ref(fe, offset); | ||
1478 | |||
1479 | return state->set_param_save(fe, fep); | ||
1480 | } | ||
1481 | |||
1482 | static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) | ||
1483 | { | ||
1484 | struct dib0700_adapter_state *st = adap->priv; | ||
1485 | struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, | ||
1486 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
1487 | |||
1488 | if (adap->id == 0) { | ||
1489 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
1490 | &dib807x_dib0070_config[0]) == NULL) | ||
1491 | return -ENODEV; | ||
1492 | } else { | ||
1493 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
1494 | &dib807x_dib0070_config[1]) == NULL) | ||
1495 | return -ENODEV; | ||
1496 | } | ||
1497 | |||
1498 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
1499 | adap->fe->ops.tuner_ops.set_params = dib807x_set_param_override; | ||
1500 | return 0; | ||
1501 | } | ||
1502 | |||
1503 | |||
1504 | /* STK807x */ | ||
1505 | static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) | ||
1506 | { | ||
1507 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
1508 | msleep(10); | ||
1509 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
1510 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
1511 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
1512 | |||
1513 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
1514 | |||
1515 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
1516 | |||
1517 | msleep(10); | ||
1518 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
1519 | msleep(10); | ||
1520 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
1521 | |||
1522 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
1523 | 0x80); | ||
1524 | |||
1525 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | ||
1526 | &dib807x_dib8000_config[0]); | ||
1527 | |||
1528 | return adap->fe == NULL ? -ENODEV : 0; | ||
1529 | } | ||
1530 | |||
1531 | /* STK807xPVR */ | ||
1532 | static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | ||
1533 | { | ||
1534 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
1535 | msleep(30); | ||
1536 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
1537 | msleep(500); | ||
1538 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
1539 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
1540 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
1541 | |||
1542 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
1543 | |||
1544 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
1545 | |||
1546 | msleep(10); | ||
1547 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
1548 | msleep(10); | ||
1549 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
1550 | |||
1551 | /* initialize IC 0 */ | ||
1552 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x80); | ||
1553 | |||
1554 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | ||
1555 | &dib807x_dib8000_config[0]); | ||
1556 | |||
1557 | return adap->fe == NULL ? -ENODEV : 0; | ||
1558 | } | ||
1559 | |||
1560 | static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) | ||
1561 | { | ||
1562 | /* initialize IC 1 */ | ||
1563 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x82); | ||
1564 | |||
1565 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, | ||
1566 | &dib807x_dib8000_config[1]); | ||
1567 | |||
1568 | return adap->fe == NULL ? -ENODEV : 0; | ||
1569 | } | ||
1570 | |||
1571 | |||
1220 | /* STK7070PD */ | 1572 | /* STK7070PD */ |
1221 | static struct dib7000p_config stk7070pd_dib7000p_config[2] = { | 1573 | static struct dib7000p_config stk7070pd_dib7000p_config[2] = { |
1222 | { | 1574 | { |
@@ -1500,7 +1852,15 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
1500 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, | 1852 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, |
1501 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, | 1853 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, |
1502 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, | 1854 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, |
1503 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, | 1855 | /* 55 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, |
1856 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73A) }, | ||
1857 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, | ||
1858 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, | ||
1859 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7770P) }, | ||
1860 | /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, | ||
1861 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, | ||
1862 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, | ||
1863 | { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, | ||
1504 | { 0 } /* Terminating entry */ | 1864 | { 0 } /* Terminating entry */ |
1505 | }; | 1865 | }; |
1506 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 1866 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -1565,7 +1925,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1565 | { NULL }, | 1925 | { NULL }, |
1566 | }, | 1926 | }, |
1567 | { "Leadtek Winfast DTV Dongle (STK7700P based)", | 1927 | { "Leadtek Winfast DTV Dongle (STK7700P based)", |
1568 | { &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] }, | 1928 | { &dib0700_usb_id_table[8] }, |
1569 | { NULL }, | 1929 | { NULL }, |
1570 | }, | 1930 | }, |
1571 | { "AVerMedia AVerTV DVB-T Express", | 1931 | { "AVerMedia AVerTV DVB-T Express", |
@@ -1764,6 +2124,41 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1764 | 2124 | ||
1765 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2125 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
1766 | 2126 | ||
2127 | .num_adapters = 1, | ||
2128 | .adapter = { | ||
2129 | { | ||
2130 | .frontend_attach = stk7070p_frontend_attach, | ||
2131 | .tuner_attach = dib7070p_tuner_attach, | ||
2132 | |||
2133 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
2134 | |||
2135 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
2136 | }, | ||
2137 | }, | ||
2138 | |||
2139 | .num_device_descs = 3, | ||
2140 | .devices = { | ||
2141 | { "Pinnacle PCTV 73A", | ||
2142 | { &dib0700_usb_id_table[56], NULL }, | ||
2143 | { NULL }, | ||
2144 | }, | ||
2145 | { "Pinnacle PCTV 73e SE", | ||
2146 | { &dib0700_usb_id_table[57], NULL }, | ||
2147 | { NULL }, | ||
2148 | }, | ||
2149 | { "Pinnacle PCTV 282e", | ||
2150 | { &dib0700_usb_id_table[58], NULL }, | ||
2151 | { NULL }, | ||
2152 | }, | ||
2153 | }, | ||
2154 | |||
2155 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
2156 | .rc_key_map = dib0700_rc_keys, | ||
2157 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
2158 | .rc_query = dib0700_rc_query | ||
2159 | |||
2160 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
2161 | |||
1767 | .num_adapters = 2, | 2162 | .num_adapters = 2, |
1768 | .adapter = { | 2163 | .adapter = { |
1769 | { | 2164 | { |
@@ -1927,6 +2322,102 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1927 | { NULL }, | 2322 | { NULL }, |
1928 | }, | 2323 | }, |
1929 | }, | 2324 | }, |
2325 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
2326 | |||
2327 | .num_adapters = 1, | ||
2328 | .adapter = { | ||
2329 | { | ||
2330 | .frontend_attach = stk7070p_frontend_attach, | ||
2331 | .tuner_attach = dib7770p_tuner_attach, | ||
2332 | |||
2333 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
2334 | |||
2335 | .size_of_priv = | ||
2336 | sizeof(struct dib0700_adapter_state), | ||
2337 | }, | ||
2338 | }, | ||
2339 | |||
2340 | .num_device_descs = 2, | ||
2341 | .devices = { | ||
2342 | { "DiBcom STK7770P reference design", | ||
2343 | { &dib0700_usb_id_table[59], NULL }, | ||
2344 | { NULL }, | ||
2345 | }, | ||
2346 | { "Terratec Cinergy T USB XXS (HD)", | ||
2347 | { &dib0700_usb_id_table[34], &dib0700_usb_id_table[60] }, | ||
2348 | { NULL }, | ||
2349 | }, | ||
2350 | }, | ||
2351 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
2352 | .rc_key_map = dib0700_rc_keys, | ||
2353 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
2354 | .rc_query = dib0700_rc_query | ||
2355 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
2356 | .num_adapters = 1, | ||
2357 | .adapter = { | ||
2358 | { | ||
2359 | .frontend_attach = stk807x_frontend_attach, | ||
2360 | .tuner_attach = dib807x_tuner_attach, | ||
2361 | |||
2362 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
2363 | |||
2364 | .size_of_priv = | ||
2365 | sizeof(struct dib0700_adapter_state), | ||
2366 | }, | ||
2367 | }, | ||
2368 | |||
2369 | .num_device_descs = 2, | ||
2370 | .devices = { | ||
2371 | { "DiBcom STK807xP reference design", | ||
2372 | { &dib0700_usb_id_table[62], NULL }, | ||
2373 | { NULL }, | ||
2374 | }, | ||
2375 | { "Prolink Pixelview SBTVD", | ||
2376 | { &dib0700_usb_id_table[63], NULL }, | ||
2377 | { NULL }, | ||
2378 | }, | ||
2379 | }, | ||
2380 | |||
2381 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
2382 | .rc_key_map = dib0700_rc_keys, | ||
2383 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
2384 | .rc_query = dib0700_rc_query | ||
2385 | |||
2386 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
2387 | .num_adapters = 2, | ||
2388 | .adapter = { | ||
2389 | { | ||
2390 | .frontend_attach = stk807xpvr_frontend_attach0, | ||
2391 | .tuner_attach = dib807x_tuner_attach, | ||
2392 | |||
2393 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
2394 | |||
2395 | .size_of_priv = | ||
2396 | sizeof(struct dib0700_adapter_state), | ||
2397 | }, | ||
2398 | { | ||
2399 | .frontend_attach = stk807xpvr_frontend_attach1, | ||
2400 | .tuner_attach = dib807x_tuner_attach, | ||
2401 | |||
2402 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
2403 | |||
2404 | .size_of_priv = | ||
2405 | sizeof(struct dib0700_adapter_state), | ||
2406 | }, | ||
2407 | }, | ||
2408 | |||
2409 | .num_device_descs = 1, | ||
2410 | .devices = { | ||
2411 | { "DiBcom STK807xPVR reference design", | ||
2412 | { &dib0700_usb_id_table[61], NULL }, | ||
2413 | { NULL }, | ||
2414 | }, | ||
2415 | }, | ||
2416 | |||
2417 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
2418 | .rc_key_map = dib0700_rc_keys, | ||
2419 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
2420 | .rc_query = dib0700_rc_query | ||
1930 | }, | 2421 | }, |
1931 | }; | 2422 | }; |
1932 | 2423 | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 185a5069b10b..a548c14c1944 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define USB_VID_MSI_2 0x1462 | 46 | #define USB_VID_MSI_2 0x1462 |
47 | #define USB_VID_OPERA1 0x695c | 47 | #define USB_VID_OPERA1 0x695c |
48 | #define USB_VID_PINNACLE 0x2304 | 48 | #define USB_VID_PINNACLE 0x2304 |
49 | #define USB_VID_PIXELVIEW 0x1554 | ||
49 | #define USB_VID_TECHNOTREND 0x0b48 | 50 | #define USB_VID_TECHNOTREND 0x0b48 |
50 | #define USB_VID_TERRATEC 0x0ccd | 51 | #define USB_VID_TERRATEC 0x0ccd |
51 | #define USB_VID_TELESTAR 0x10b9 | 52 | #define USB_VID_TELESTAR 0x10b9 |
@@ -59,6 +60,7 @@ | |||
59 | #define USB_VID_YUAN 0x1164 | 60 | #define USB_VID_YUAN 0x1164 |
60 | #define USB_VID_XTENSIONS 0x1ae7 | 61 | #define USB_VID_XTENSIONS 0x1ae7 |
61 | #define USB_VID_HUMAX_COEX 0x10b9 | 62 | #define USB_VID_HUMAX_COEX 0x10b9 |
63 | #define USB_VID_774 0x7a69 | ||
62 | 64 | ||
63 | /* Product IDs */ | 65 | /* Product IDs */ |
64 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | 66 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 |
@@ -95,7 +97,10 @@ | |||
95 | #define USB_PID_DIBCOM_STK7700_U7000 0x7001 | 97 | #define USB_PID_DIBCOM_STK7700_U7000 0x7001 |
96 | #define USB_PID_DIBCOM_STK7070P 0x1ebc | 98 | #define USB_PID_DIBCOM_STK7070P 0x1ebc |
97 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe | 99 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe |
100 | #define USB_PID_DIBCOM_STK807XP 0x1f90 | ||
101 | #define USB_PID_DIBCOM_STK807XPVR 0x1f98 | ||
98 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | 102 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
103 | #define USB_PID_DIBCOM_STK7770P 0x1e80 | ||
99 | #define USB_PID_DPOSH_M9206_COLD 0x9206 | 104 | #define USB_PID_DPOSH_M9206_COLD 0x9206 |
100 | #define USB_PID_DPOSH_M9206_WARM 0xa090 | 105 | #define USB_PID_DPOSH_M9206_WARM 0xa090 |
101 | #define USB_PID_UNIWILL_STK7700P 0x6003 | 106 | #define USB_PID_UNIWILL_STK7700P 0x6003 |
@@ -184,6 +189,7 @@ | |||
184 | #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 | 189 | #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 |
185 | #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 | 190 | #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 |
186 | #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 | 191 | #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 |
192 | #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab | ||
187 | #define USB_PID_TERRATEC_T3 0x10a0 | 193 | #define USB_PID_TERRATEC_T3 0x10a0 |
188 | #define USB_PID_TERRATEC_T5 0x10a1 | 194 | #define USB_PID_TERRATEC_T5 0x10a1 |
189 | #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e | 195 | #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e |
@@ -195,6 +201,10 @@ | |||
195 | #define USB_PID_PINNACLE_PCTV73E 0x0237 | 201 | #define USB_PID_PINNACLE_PCTV73E 0x0237 |
196 | #define USB_PID_PINNACLE_PCTV801E 0x023a | 202 | #define USB_PID_PINNACLE_PCTV801E 0x023a |
197 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | 203 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b |
204 | #define USB_PID_PINNACLE_PCTV73A 0x0243 | ||
205 | #define USB_PID_PINNACLE_PCTV73ESE 0x0245 | ||
206 | #define USB_PID_PINNACLE_PCTV282E 0x0248 | ||
207 | #define USB_PID_PIXELVIEW_SBTVD 0x5010 | ||
198 | #define USB_PID_PCTV_200E 0x020e | 208 | #define USB_PID_PCTV_200E 0x020e |
199 | #define USB_PID_PCTV_400E 0x020f | 209 | #define USB_PID_PCTV_400E 0x020f |
200 | #define USB_PID_PCTV_450E 0x0222 | 210 | #define USB_PID_PCTV_450E 0x0222 |
@@ -265,5 +275,6 @@ | |||
265 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 | 275 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 |
266 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 | 276 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 |
267 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 | 277 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 |
278 | #define USB_PID_FRIIO_WHITE 0x0001 | ||
268 | 279 | ||
269 | #endif | 280 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c new file mode 100644 index 000000000000..c4dfe25cf60d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/friio-fe.c | |||
@@ -0,0 +1,483 @@ | |||
1 | /* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver. | ||
2 | * | ||
3 | * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp> | ||
4 | * | ||
5 | * This module is based off the the gl861 and vp702x modules. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation, version 2. | ||
10 | * | ||
11 | * see Documentation/dvb/README.dvb-usb for more information | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | #include "friio.h" | ||
18 | |||
19 | struct jdvbt90502_state { | ||
20 | struct i2c_adapter *i2c; | ||
21 | struct dvb_frontend frontend; | ||
22 | struct jdvbt90502_config config; | ||
23 | }; | ||
24 | |||
25 | /* NOTE: TC90502 has 16bit register-address? */ | ||
26 | /* register 0x0100 is used for reading PLL status, so reg is u16 here */ | ||
27 | static int jdvbt90502_reg_read(struct jdvbt90502_state *state, | ||
28 | const u16 reg, u8 *buf, const size_t count) | ||
29 | { | ||
30 | int ret; | ||
31 | u8 wbuf[3]; | ||
32 | struct i2c_msg msg[2]; | ||
33 | |||
34 | wbuf[0] = reg & 0xFF; | ||
35 | wbuf[1] = 0; | ||
36 | wbuf[2] = reg >> 8; | ||
37 | |||
38 | msg[0].addr = state->config.demod_address; | ||
39 | msg[0].flags = 0; | ||
40 | msg[0].buf = wbuf; | ||
41 | msg[0].len = sizeof(wbuf); | ||
42 | |||
43 | msg[1].addr = msg[0].addr; | ||
44 | msg[1].flags = I2C_M_RD; | ||
45 | msg[1].buf = buf; | ||
46 | msg[1].len = count; | ||
47 | |||
48 | ret = i2c_transfer(state->i2c, msg, 2); | ||
49 | if (ret != 2) { | ||
50 | deb_fe(" reg read failed.\n"); | ||
51 | return -EREMOTEIO; | ||
52 | } | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | /* currently 16bit register-address is not used, so reg is u8 here */ | ||
57 | static int jdvbt90502_single_reg_write(struct jdvbt90502_state *state, | ||
58 | const u8 reg, const u8 val) | ||
59 | { | ||
60 | struct i2c_msg msg; | ||
61 | u8 wbuf[2]; | ||
62 | |||
63 | wbuf[0] = reg; | ||
64 | wbuf[1] = val; | ||
65 | |||
66 | msg.addr = state->config.demod_address; | ||
67 | msg.flags = 0; | ||
68 | msg.buf = wbuf; | ||
69 | msg.len = sizeof(wbuf); | ||
70 | |||
71 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | ||
72 | deb_fe(" reg write failed."); | ||
73 | return -EREMOTEIO; | ||
74 | } | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int _jdvbt90502_write(struct dvb_frontend *fe, u8 *buf, int len) | ||
79 | { | ||
80 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
81 | int err, i; | ||
82 | for (i = 0; i < len - 1; i++) { | ||
83 | err = jdvbt90502_single_reg_write(state, | ||
84 | buf[0] + i, buf[i + 1]); | ||
85 | if (err) | ||
86 | return err; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /* read pll status byte via the demodulator's I2C register */ | ||
93 | /* note: Win box reads it by 8B block at the I2C addr 0x30 from reg:0x80 */ | ||
94 | static int jdvbt90502_pll_read(struct jdvbt90502_state *state, u8 *result) | ||
95 | { | ||
96 | int ret; | ||
97 | |||
98 | /* +1 for reading */ | ||
99 | u8 pll_addr_byte = (state->config.pll_address << 1) + 1; | ||
100 | |||
101 | *result = 0; | ||
102 | |||
103 | ret = jdvbt90502_single_reg_write(state, JDVBT90502_2ND_I2C_REG, | ||
104 | pll_addr_byte); | ||
105 | if (ret) | ||
106 | goto error; | ||
107 | |||
108 | ret = jdvbt90502_reg_read(state, 0x0100, result, 1); | ||
109 | if (ret) | ||
110 | goto error; | ||
111 | |||
112 | deb_fe("PLL read val:%02x\n", *result); | ||
113 | return 0; | ||
114 | |||
115 | error: | ||
116 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
117 | return -EREMOTEIO; | ||
118 | } | ||
119 | |||
120 | |||
121 | /* set pll frequency via the demodulator's I2C register */ | ||
122 | static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq) | ||
123 | { | ||
124 | int ret; | ||
125 | int retry; | ||
126 | u8 res1; | ||
127 | u8 res2[9]; | ||
128 | |||
129 | u8 pll_freq_cmd[PLL_CMD_LEN]; | ||
130 | u8 pll_agc_cmd[PLL_CMD_LEN]; | ||
131 | struct i2c_msg msg[2]; | ||
132 | u32 f; | ||
133 | |||
134 | deb_fe("%s: freq=%d, step=%d\n", __func__, freq, | ||
135 | state->frontend.ops.info.frequency_stepsize); | ||
136 | /* freq -> oscilator frequency conversion. */ | ||
137 | /* freq: 473,000,000 + n*6,000,000 (no 1/7MHz shift to center freq) */ | ||
138 | /* add 400[1/7 MHZ] = 57.142857MHz. 57MHz for the IF, */ | ||
139 | /* 1/7MHz for center freq shift */ | ||
140 | f = freq / state->frontend.ops.info.frequency_stepsize; | ||
141 | f += 400; | ||
142 | pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */ | ||
143 | pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1; | ||
144 | pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F; | ||
145 | pll_freq_cmd[DIVIDER_BYTE2] = f & 0xFF; | ||
146 | pll_freq_cmd[CONTROL_BYTE] = 0xB2; /* ref.divider:28, 4MHz/28=1/7MHz */ | ||
147 | pll_freq_cmd[BANDSWITCH_BYTE] = 0x08; /* UHF band */ | ||
148 | |||
149 | msg[0].addr = state->config.demod_address; | ||
150 | msg[0].flags = 0; | ||
151 | msg[0].buf = pll_freq_cmd; | ||
152 | msg[0].len = sizeof(pll_freq_cmd); | ||
153 | |||
154 | ret = i2c_transfer(state->i2c, &msg[0], 1); | ||
155 | if (ret != 1) | ||
156 | goto error; | ||
157 | |||
158 | udelay(50); | ||
159 | |||
160 | pll_agc_cmd[DEMOD_REDIRECT_REG] = pll_freq_cmd[DEMOD_REDIRECT_REG]; | ||
161 | pll_agc_cmd[ADDRESS_BYTE] = pll_freq_cmd[ADDRESS_BYTE]; | ||
162 | pll_agc_cmd[DIVIDER_BYTE1] = pll_freq_cmd[DIVIDER_BYTE1]; | ||
163 | pll_agc_cmd[DIVIDER_BYTE2] = pll_freq_cmd[DIVIDER_BYTE2]; | ||
164 | pll_agc_cmd[CONTROL_BYTE] = 0x9A; /* AGC_CTRL instead of BANDSWITCH */ | ||
165 | pll_agc_cmd[AGC_CTRL_BYTE] = 0x50; | ||
166 | /* AGC Time Constant 2s, AGC take-over point:103dBuV(lowest) */ | ||
167 | |||
168 | msg[1].addr = msg[0].addr; | ||
169 | msg[1].flags = 0; | ||
170 | msg[1].buf = pll_agc_cmd; | ||
171 | msg[1].len = sizeof(pll_agc_cmd); | ||
172 | |||
173 | ret = i2c_transfer(state->i2c, &msg[1], 1); | ||
174 | if (ret != 1) | ||
175 | goto error; | ||
176 | |||
177 | /* I don't know what these cmds are for, */ | ||
178 | /* but the USB log on a windows box contains them */ | ||
179 | ret = jdvbt90502_single_reg_write(state, 0x01, 0x40); | ||
180 | ret |= jdvbt90502_single_reg_write(state, 0x01, 0x00); | ||
181 | if (ret) | ||
182 | goto error; | ||
183 | udelay(100); | ||
184 | |||
185 | /* wait for the demod to be ready? */ | ||
186 | #define RETRY_COUNT 5 | ||
187 | for (retry = 0; retry < RETRY_COUNT; retry++) { | ||
188 | ret = jdvbt90502_reg_read(state, 0x0096, &res1, 1); | ||
189 | if (ret) | ||
190 | goto error; | ||
191 | /* if (res1 != 0x00) goto error; */ | ||
192 | ret = jdvbt90502_reg_read(state, 0x00B0, res2, sizeof(res2)); | ||
193 | if (ret) | ||
194 | goto error; | ||
195 | if (res2[0] >= 0xA7) | ||
196 | break; | ||
197 | msleep(100); | ||
198 | } | ||
199 | if (retry >= RETRY_COUNT) { | ||
200 | deb_fe("%s: FE does not get ready after freq setting.\n", | ||
201 | __func__); | ||
202 | return -EREMOTEIO; | ||
203 | } | ||
204 | |||
205 | return 0; | ||
206 | error: | ||
207 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
208 | return -EREMOTEIO; | ||
209 | } | ||
210 | |||
211 | static int jdvbt90502_read_status(struct dvb_frontend *fe, fe_status_t *state) | ||
212 | { | ||
213 | u8 result; | ||
214 | int ret; | ||
215 | |||
216 | *state = FE_HAS_SIGNAL; | ||
217 | |||
218 | ret = jdvbt90502_pll_read(fe->demodulator_priv, &result); | ||
219 | if (ret) { | ||
220 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
221 | return -EREMOTEIO; | ||
222 | } | ||
223 | |||
224 | *state = FE_HAS_SIGNAL | ||
225 | | FE_HAS_CARRIER | ||
226 | | FE_HAS_VITERBI | ||
227 | | FE_HAS_SYNC; | ||
228 | |||
229 | if (result & PLL_STATUS_LOCKED) | ||
230 | *state |= FE_HAS_LOCK; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int jdvbt90502_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
236 | { | ||
237 | *ber = 0; | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe, | ||
242 | u16 *strength) | ||
243 | { | ||
244 | int ret; | ||
245 | u8 rbuf[37]; | ||
246 | |||
247 | *strength = 0; | ||
248 | |||
249 | /* status register (incl. signal strength) : 0x89 */ | ||
250 | /* TODO: read just the necessary registers [0x8B..0x8D]? */ | ||
251 | ret = jdvbt90502_reg_read(fe->demodulator_priv, 0x0089, | ||
252 | rbuf, sizeof(rbuf)); | ||
253 | |||
254 | if (ret) { | ||
255 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
256 | return -EREMOTEIO; | ||
257 | } | ||
258 | |||
259 | /* signal_strength: rbuf[2-4] (24bit BE), use lower 16bit for now. */ | ||
260 | *strength = (rbuf[3] << 8) + rbuf[4]; | ||
261 | if (rbuf[2]) | ||
262 | *strength = 0xffff; | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int jdvbt90502_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
268 | { | ||
269 | *snr = 0x0101; | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int jdvbt90502_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
274 | { | ||
275 | *ucblocks = 0; | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int jdvbt90502_get_tune_settings(struct dvb_frontend *fe, | ||
280 | struct dvb_frontend_tune_settings *fs) | ||
281 | { | ||
282 | fs->min_delay_ms = 500; | ||
283 | fs->step_size = 0; | ||
284 | fs->max_drift = 0; | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int jdvbt90502_get_frontend(struct dvb_frontend *fe, | ||
290 | struct dvb_frontend_parameters *p) | ||
291 | { | ||
292 | p->inversion = INVERSION_AUTO; | ||
293 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
294 | p->u.ofdm.code_rate_HP = FEC_AUTO; | ||
295 | p->u.ofdm.code_rate_LP = FEC_AUTO; | ||
296 | p->u.ofdm.constellation = QAM_64; | ||
297 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | ||
298 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | ||
299 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int jdvbt90502_set_frontend(struct dvb_frontend *fe, | ||
304 | struct dvb_frontend_parameters *p) | ||
305 | { | ||
306 | /** | ||
307 | * NOTE: ignore all the paramters except frequency. | ||
308 | * others should be fixed to the proper value for ISDB-T, | ||
309 | * but don't check here. | ||
310 | */ | ||
311 | |||
312 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
313 | int ret; | ||
314 | |||
315 | deb_fe("%s: Freq:%d\n", __func__, p->frequency); | ||
316 | |||
317 | ret = jdvbt90502_pll_set_freq(state, p->frequency); | ||
318 | if (ret) { | ||
319 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
320 | return -EREMOTEIO; | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int jdvbt90502_sleep(struct dvb_frontend *fe) | ||
327 | { | ||
328 | deb_fe("%s called.\n", __func__); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | |||
333 | /** | ||
334 | * (reg, val) commad list to initialize this module. | ||
335 | * captured on a Windows box. | ||
336 | */ | ||
337 | static u8 init_code[][2] = { | ||
338 | {0x01, 0x40}, | ||
339 | {0x04, 0x38}, | ||
340 | {0x05, 0x40}, | ||
341 | {0x07, 0x40}, | ||
342 | {0x0F, 0x4F}, | ||
343 | {0x11, 0x21}, | ||
344 | {0x12, 0x0B}, | ||
345 | {0x13, 0x2F}, | ||
346 | {0x14, 0x31}, | ||
347 | {0x16, 0x02}, | ||
348 | {0x21, 0xC4}, | ||
349 | {0x22, 0x20}, | ||
350 | {0x2C, 0x79}, | ||
351 | {0x2D, 0x34}, | ||
352 | {0x2F, 0x00}, | ||
353 | {0x30, 0x28}, | ||
354 | {0x31, 0x31}, | ||
355 | {0x32, 0xDF}, | ||
356 | {0x38, 0x01}, | ||
357 | {0x39, 0x78}, | ||
358 | {0x3B, 0x33}, | ||
359 | {0x3C, 0x33}, | ||
360 | {0x48, 0x90}, | ||
361 | {0x51, 0x68}, | ||
362 | {0x5E, 0x38}, | ||
363 | {0x71, 0x00}, | ||
364 | {0x72, 0x08}, | ||
365 | {0x77, 0x00}, | ||
366 | {0xC0, 0x21}, | ||
367 | {0xC1, 0x10}, | ||
368 | {0xE4, 0x1A}, | ||
369 | {0xEA, 0x1F}, | ||
370 | {0x77, 0x00}, | ||
371 | {0x71, 0x00}, | ||
372 | {0x71, 0x00}, | ||
373 | {0x76, 0x0C}, | ||
374 | }; | ||
375 | |||
376 | const static int init_code_len = sizeof(init_code) / sizeof(u8[2]); | ||
377 | |||
378 | static int jdvbt90502_init(struct dvb_frontend *fe) | ||
379 | { | ||
380 | int i = -1; | ||
381 | int ret; | ||
382 | struct i2c_msg msg; | ||
383 | |||
384 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
385 | |||
386 | deb_fe("%s called.\n", __func__); | ||
387 | |||
388 | msg.addr = state->config.demod_address; | ||
389 | msg.flags = 0; | ||
390 | msg.len = 2; | ||
391 | for (i = 0; i < init_code_len; i++) { | ||
392 | msg.buf = init_code[i]; | ||
393 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
394 | if (ret != 1) | ||
395 | goto error; | ||
396 | } | ||
397 | msleep(100); | ||
398 | |||
399 | return 0; | ||
400 | |||
401 | error: | ||
402 | deb_fe("%s: init_code[%d] failed. ret==%d\n", __func__, i, ret); | ||
403 | return -EREMOTEIO; | ||
404 | } | ||
405 | |||
406 | |||
407 | static void jdvbt90502_release(struct dvb_frontend *fe) | ||
408 | { | ||
409 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
410 | kfree(state); | ||
411 | } | ||
412 | |||
413 | |||
414 | static struct dvb_frontend_ops jdvbt90502_ops; | ||
415 | |||
416 | struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d) | ||
417 | { | ||
418 | struct jdvbt90502_state *state = NULL; | ||
419 | |||
420 | deb_info("%s called.\n", __func__); | ||
421 | |||
422 | /* allocate memory for the internal state */ | ||
423 | state = kzalloc(sizeof(struct jdvbt90502_state), GFP_KERNEL); | ||
424 | if (state == NULL) | ||
425 | goto error; | ||
426 | |||
427 | /* setup the state */ | ||
428 | state->i2c = &d->i2c_adap; | ||
429 | memcpy(&state->config, &friio_fe_config, sizeof(friio_fe_config)); | ||
430 | |||
431 | /* create dvb_frontend */ | ||
432 | memcpy(&state->frontend.ops, &jdvbt90502_ops, | ||
433 | sizeof(jdvbt90502_ops)); | ||
434 | state->frontend.demodulator_priv = state; | ||
435 | |||
436 | if (jdvbt90502_init(&state->frontend) < 0) | ||
437 | goto error; | ||
438 | |||
439 | return &state->frontend; | ||
440 | |||
441 | error: | ||
442 | kfree(state); | ||
443 | return NULL; | ||
444 | } | ||
445 | |||
446 | static struct dvb_frontend_ops jdvbt90502_ops = { | ||
447 | |||
448 | .info = { | ||
449 | .name = "Comtech JDVBT90502 ISDB-T", | ||
450 | .type = FE_OFDM, | ||
451 | .frequency_min = 473000000, /* UHF 13ch, center */ | ||
452 | .frequency_max = 767142857, /* UHF 62ch, center */ | ||
453 | .frequency_stepsize = JDVBT90502_PLL_CLK / | ||
454 | JDVBT90502_PLL_DIVIDER, | ||
455 | .frequency_tolerance = 0, | ||
456 | |||
457 | /* NOTE: this driver ignores all parameters but frequency. */ | ||
458 | .caps = FE_CAN_INVERSION_AUTO | | ||
459 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
460 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | | ||
461 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | | ||
462 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
463 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
464 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
465 | FE_CAN_HIERARCHY_AUTO, | ||
466 | }, | ||
467 | |||
468 | .release = jdvbt90502_release, | ||
469 | |||
470 | .init = jdvbt90502_init, | ||
471 | .sleep = jdvbt90502_sleep, | ||
472 | .write = _jdvbt90502_write, | ||
473 | |||
474 | .set_frontend = jdvbt90502_set_frontend, | ||
475 | .get_frontend = jdvbt90502_get_frontend, | ||
476 | .get_tune_settings = jdvbt90502_get_tune_settings, | ||
477 | |||
478 | .read_status = jdvbt90502_read_status, | ||
479 | .read_ber = jdvbt90502_read_ber, | ||
480 | .read_signal_strength = jdvbt90502_read_signal_strength, | ||
481 | .read_snr = jdvbt90502_read_snr, | ||
482 | .read_ucblocks = jdvbt90502_read_ucblocks, | ||
483 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/dvb/dvb-usb/friio.c new file mode 100644 index 000000000000..14a65b4aec07 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/friio.c | |||
@@ -0,0 +1,525 @@ | |||
1 | /* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver. | ||
2 | * | ||
3 | * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp> | ||
4 | * | ||
5 | * This module is based off the the gl861 and vp702x modules. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation, version 2. | ||
10 | * | ||
11 | * see Documentation/dvb/README.dvb-usb for more information | ||
12 | */ | ||
13 | #include "friio.h" | ||
14 | |||
15 | /* debug */ | ||
16 | int dvb_usb_friio_debug; | ||
17 | module_param_named(debug, dvb_usb_friio_debug, int, 0644); | ||
18 | MODULE_PARM_DESC(debug, | ||
19 | "set debugging level (1=info,2=xfer,4=rc,8=fe (or-able))." | ||
20 | DVB_USB_DEBUG_STATUS); | ||
21 | |||
22 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
23 | |||
24 | /** | ||
25 | * Indirect I2C access to the PLL via FE. | ||
26 | * whole I2C protocol data to the PLL is sent via the FE's I2C register. | ||
27 | * This is done by a control msg to the FE with the I2C data accompanied, and | ||
28 | * a specific USB request number is assigned for that purpose. | ||
29 | * | ||
30 | * this func sends wbuf[1..] to the I2C register wbuf[0] at addr (= at FE). | ||
31 | * TODO: refoctored, smarter i2c functions. | ||
32 | */ | ||
33 | static int gl861_i2c_ctrlmsg_data(struct dvb_usb_device *d, u8 addr, | ||
34 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
35 | { | ||
36 | u16 index = wbuf[0]; /* must be JDVBT90502_2ND_I2C_REG(=0xFE) */ | ||
37 | u16 value = addr << (8 + 1); | ||
38 | int wo = (rbuf == NULL || rlen == 0); /* write only */ | ||
39 | u8 req, type; | ||
40 | |||
41 | deb_xfer("write to PLL:0x%02x via FE reg:0x%02x, len:%d\n", | ||
42 | wbuf[1], wbuf[0], wlen - 1); | ||
43 | |||
44 | if (wo && wlen >= 2) { | ||
45 | req = GL861_REQ_I2C_DATA_CTRL_WRITE; | ||
46 | type = GL861_WRITE; | ||
47 | udelay(20); | ||
48 | return usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
49 | req, type, value, index, | ||
50 | &wbuf[1], wlen - 1, 2000); | ||
51 | } | ||
52 | |||
53 | deb_xfer("not supported ctrl-msg, aborting."); | ||
54 | return -EINVAL; | ||
55 | } | ||
56 | |||
57 | /* normal I2C access (without extra data arguments). | ||
58 | * write to the register wbuf[0] at I2C address addr with the value wbuf[1], | ||
59 | * or read from the register wbuf[0]. | ||
60 | * register address can be 16bit (wbuf[2]<<8 | wbuf[0]) if wlen==3 | ||
61 | */ | ||
62 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
63 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
64 | { | ||
65 | u16 index; | ||
66 | u16 value = addr << (8 + 1); | ||
67 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
68 | u8 req, type; | ||
69 | unsigned int pipe; | ||
70 | |||
71 | /* special case for the indirect I2C access to the PLL via FE, */ | ||
72 | if (addr == friio_fe_config.demod_address && | ||
73 | wbuf[0] == JDVBT90502_2ND_I2C_REG) | ||
74 | return gl861_i2c_ctrlmsg_data(d, addr, wbuf, wlen, rbuf, rlen); | ||
75 | |||
76 | if (wo) { | ||
77 | req = GL861_REQ_I2C_WRITE; | ||
78 | type = GL861_WRITE; | ||
79 | pipe = usb_sndctrlpipe(d->udev, 0); | ||
80 | } else { /* rw */ | ||
81 | req = GL861_REQ_I2C_READ; | ||
82 | type = GL861_READ; | ||
83 | pipe = usb_rcvctrlpipe(d->udev, 0); | ||
84 | } | ||
85 | |||
86 | switch (wlen) { | ||
87 | case 1: | ||
88 | index = wbuf[0]; | ||
89 | break; | ||
90 | case 2: | ||
91 | index = wbuf[0]; | ||
92 | value = value + wbuf[1]; | ||
93 | break; | ||
94 | case 3: | ||
95 | /* special case for 16bit register-address */ | ||
96 | index = (wbuf[2] << 8) | wbuf[0]; | ||
97 | value = value + wbuf[1]; | ||
98 | break; | ||
99 | default: | ||
100 | deb_xfer("wlen = %x, aborting.", wlen); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | msleep(1); | ||
104 | return usb_control_msg(d->udev, pipe, req, type, | ||
105 | value, index, rbuf, rlen, 2000); | ||
106 | } | ||
107 | |||
108 | /* I2C */ | ||
109 | static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
110 | int num) | ||
111 | { | ||
112 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
113 | int i; | ||
114 | |||
115 | |||
116 | if (num > 2) | ||
117 | return -EINVAL; | ||
118 | |||
119 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
120 | return -EAGAIN; | ||
121 | |||
122 | for (i = 0; i < num; i++) { | ||
123 | /* write/read request */ | ||
124 | if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) { | ||
125 | if (gl861_i2c_msg(d, msg[i].addr, | ||
126 | msg[i].buf, msg[i].len, | ||
127 | msg[i + 1].buf, msg[i + 1].len) < 0) | ||
128 | break; | ||
129 | i++; | ||
130 | } else | ||
131 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
132 | msg[i].len, NULL, 0) < 0) | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | mutex_unlock(&d->i2c_mutex); | ||
137 | return i; | ||
138 | } | ||
139 | |||
140 | static u32 gl861_i2c_func(struct i2c_adapter *adapter) | ||
141 | { | ||
142 | return I2C_FUNC_I2C; | ||
143 | } | ||
144 | |||
145 | |||
146 | static int friio_ext_ctl(struct dvb_usb_adapter *adap, | ||
147 | u32 sat_color, int lnb_on) | ||
148 | { | ||
149 | int i; | ||
150 | int ret; | ||
151 | struct i2c_msg msg; | ||
152 | u8 buf[2]; | ||
153 | u32 mask; | ||
154 | u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0; | ||
155 | |||
156 | msg.addr = 0x00; | ||
157 | msg.flags = 0; | ||
158 | msg.len = 2; | ||
159 | msg.buf = buf; | ||
160 | |||
161 | buf[0] = 0x00; | ||
162 | |||
163 | /* send 2bit header (&B10) */ | ||
164 | buf[1] = lnb | FRIIO_CTL_LED | FRIIO_CTL_STROBE; | ||
165 | ret = gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
166 | buf[1] |= FRIIO_CTL_CLK; | ||
167 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
168 | |||
169 | buf[1] = lnb | FRIIO_CTL_STROBE; | ||
170 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
171 | buf[1] |= FRIIO_CTL_CLK; | ||
172 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
173 | |||
174 | /* send 32bit(satur, R, G, B) data in serial */ | ||
175 | mask = 1 << 31; | ||
176 | for (i = 0; i < 32; i++) { | ||
177 | buf[1] = lnb | FRIIO_CTL_STROBE; | ||
178 | if (sat_color & mask) | ||
179 | buf[1] |= FRIIO_CTL_LED; | ||
180 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
181 | buf[1] |= FRIIO_CTL_CLK; | ||
182 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
183 | mask >>= 1; | ||
184 | } | ||
185 | |||
186 | /* set the strobe off */ | ||
187 | buf[1] = lnb; | ||
188 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
189 | buf[1] |= FRIIO_CTL_CLK; | ||
190 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
191 | |||
192 | return (ret == 70); | ||
193 | } | ||
194 | |||
195 | |||
196 | static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); | ||
197 | |||
198 | /* TODO: move these init cmds to the FE's init routine? */ | ||
199 | static u8 streaming_init_cmds[][2] = { | ||
200 | {0x33, 0x08}, | ||
201 | {0x37, 0x40}, | ||
202 | {0x3A, 0x1F}, | ||
203 | {0x3B, 0xFF}, | ||
204 | {0x3C, 0x1F}, | ||
205 | {0x3D, 0xFF}, | ||
206 | {0x38, 0x00}, | ||
207 | {0x35, 0x00}, | ||
208 | {0x39, 0x00}, | ||
209 | {0x36, 0x00}, | ||
210 | }; | ||
211 | static int cmdlen = sizeof(streaming_init_cmds) / 2; | ||
212 | |||
213 | /* | ||
214 | * Command sequence in this init function is a replay | ||
215 | * of the captured USB commands from the Windows proprietary driver. | ||
216 | */ | ||
217 | static int friio_initialize(struct dvb_usb_device *d) | ||
218 | { | ||
219 | int ret; | ||
220 | int i; | ||
221 | int retry = 0; | ||
222 | u8 rbuf[2]; | ||
223 | u8 wbuf[3]; | ||
224 | |||
225 | deb_info("%s called.\n", __func__); | ||
226 | |||
227 | /* use gl861_i2c_msg instead of gl861_i2c_xfer(), */ | ||
228 | /* because the i2c device is not set up yet. */ | ||
229 | wbuf[0] = 0x11; | ||
230 | wbuf[1] = 0x02; | ||
231 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
232 | if (ret < 0) | ||
233 | goto error; | ||
234 | msleep(2); | ||
235 | |||
236 | wbuf[0] = 0x11; | ||
237 | wbuf[1] = 0x00; | ||
238 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
239 | if (ret < 0) | ||
240 | goto error; | ||
241 | msleep(1); | ||
242 | |||
243 | /* following msgs should be in the FE's init code? */ | ||
244 | /* cmd sequence to identify the device type? (friio black/white) */ | ||
245 | wbuf[0] = 0x03; | ||
246 | wbuf[1] = 0x80; | ||
247 | /* can't use gl861_i2c_cmd, as the register-addr is 16bit(0x0100) */ | ||
248 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
249 | GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE, | ||
250 | 0x1200, 0x0100, wbuf, 2, 2000); | ||
251 | if (ret < 0) | ||
252 | goto error; | ||
253 | |||
254 | msleep(2); | ||
255 | wbuf[0] = 0x00; | ||
256 | wbuf[2] = 0x01; /* reg.0x0100 */ | ||
257 | wbuf[1] = 0x00; | ||
258 | ret = gl861_i2c_msg(d, 0x12 >> 1, wbuf, 3, rbuf, 2); | ||
259 | /* my Friio White returns 0xffff. */ | ||
260 | if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff) | ||
261 | goto error; | ||
262 | |||
263 | msleep(2); | ||
264 | wbuf[0] = 0x03; | ||
265 | wbuf[1] = 0x80; | ||
266 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
267 | GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE, | ||
268 | 0x9000, 0x0100, wbuf, 2, 2000); | ||
269 | if (ret < 0) | ||
270 | goto error; | ||
271 | |||
272 | msleep(2); | ||
273 | wbuf[0] = 0x00; | ||
274 | wbuf[2] = 0x01; /* reg.0x0100 */ | ||
275 | wbuf[1] = 0x00; | ||
276 | ret = gl861_i2c_msg(d, 0x90 >> 1, wbuf, 3, rbuf, 2); | ||
277 | /* my Friio White returns 0xffff again. */ | ||
278 | if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff) | ||
279 | goto error; | ||
280 | |||
281 | msleep(1); | ||
282 | |||
283 | restart: | ||
284 | /* ============ start DEMOD init cmds ================== */ | ||
285 | /* read PLL status to clear the POR bit */ | ||
286 | wbuf[0] = JDVBT90502_2ND_I2C_REG; | ||
287 | wbuf[1] = (FRIIO_PLL_ADDR << 1) + 1; /* +1 for reading */ | ||
288 | ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, NULL, 0); | ||
289 | if (ret < 0) | ||
290 | goto error; | ||
291 | |||
292 | msleep(5); | ||
293 | /* note: DEMODULATOR has 16bit register-address. */ | ||
294 | wbuf[0] = 0x00; | ||
295 | wbuf[2] = 0x01; /* reg addr: 0x0100 */ | ||
296 | wbuf[1] = 0x00; /* val: not used */ | ||
297 | ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 3, rbuf, 1); | ||
298 | if (ret < 0) | ||
299 | goto error; | ||
300 | /* | ||
301 | msleep(1); | ||
302 | wbuf[0] = 0x80; | ||
303 | wbuf[1] = 0x00; | ||
304 | ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, rbuf, 1); | ||
305 | if (ret < 0) | ||
306 | goto error; | ||
307 | */ | ||
308 | if (rbuf[0] & 0x80) { /* still in PowerOnReset state? */ | ||
309 | if (++retry > 3) { | ||
310 | deb_info("failed to get the correct" | ||
311 | " FE demod status:0x%02x\n", rbuf[0]); | ||
312 | goto error; | ||
313 | } | ||
314 | msleep(100); | ||
315 | goto restart; | ||
316 | } | ||
317 | |||
318 | /* TODO: check return value in rbuf */ | ||
319 | /* =========== end DEMOD init cmds ===================== */ | ||
320 | msleep(1); | ||
321 | |||
322 | wbuf[0] = 0x30; | ||
323 | wbuf[1] = 0x04; | ||
324 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
325 | if (ret < 0) | ||
326 | goto error; | ||
327 | |||
328 | msleep(2); | ||
329 | /* following 2 cmds unnecessary? */ | ||
330 | wbuf[0] = 0x00; | ||
331 | wbuf[1] = 0x01; | ||
332 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
333 | if (ret < 0) | ||
334 | goto error; | ||
335 | |||
336 | wbuf[0] = 0x06; | ||
337 | wbuf[1] = 0x0F; | ||
338 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
339 | if (ret < 0) | ||
340 | goto error; | ||
341 | |||
342 | /* some streaming ctl cmds (maybe) */ | ||
343 | msleep(10); | ||
344 | for (i = 0; i < cmdlen; i++) { | ||
345 | ret = gl861_i2c_msg(d, 0x00, streaming_init_cmds[i], 2, | ||
346 | NULL, 0); | ||
347 | if (ret < 0) | ||
348 | goto error; | ||
349 | msleep(1); | ||
350 | } | ||
351 | msleep(20); | ||
352 | |||
353 | /* change the LED color etc. */ | ||
354 | ret = friio_streaming_ctrl(&d->adapter[0], 0); | ||
355 | if (ret < 0) | ||
356 | goto error; | ||
357 | |||
358 | return 0; | ||
359 | |||
360 | error: | ||
361 | deb_info("%s:ret == %d\n", __func__, ret); | ||
362 | return -EIO; | ||
363 | } | ||
364 | |||
365 | /* Callbacks for DVB USB */ | ||
366 | |||
367 | static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
368 | { | ||
369 | int ret; | ||
370 | |||
371 | deb_info("%s called.(%d)\n", __func__, onoff); | ||
372 | |||
373 | /* set the LED color and saturation (and LNB on) */ | ||
374 | if (onoff) | ||
375 | ret = friio_ext_ctl(adap, 0x6400ff64, 1); | ||
376 | else | ||
377 | ret = friio_ext_ctl(adap, 0x96ff00ff, 1); | ||
378 | |||
379 | if (ret != 1) { | ||
380 | deb_info("%s failed to send cmdx. ret==%d\n", __func__, ret); | ||
381 | return -EREMOTEIO; | ||
382 | } | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int friio_frontend_attach(struct dvb_usb_adapter *adap) | ||
387 | { | ||
388 | if (friio_initialize(adap->dev) < 0) | ||
389 | return -EIO; | ||
390 | |||
391 | adap->fe = jdvbt90502_attach(adap->dev); | ||
392 | if (adap->fe == NULL) | ||
393 | return -EIO; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | /* DVB USB Driver stuff */ | ||
399 | static struct dvb_usb_device_properties friio_properties; | ||
400 | |||
401 | static int friio_probe(struct usb_interface *intf, | ||
402 | const struct usb_device_id *id) | ||
403 | { | ||
404 | struct dvb_usb_device *d; | ||
405 | struct usb_host_interface *alt; | ||
406 | int ret; | ||
407 | |||
408 | if (intf->num_altsetting < GL861_ALTSETTING_COUNT) | ||
409 | return -ENODEV; | ||
410 | |||
411 | alt = usb_altnum_to_altsetting(intf, FRIIO_BULK_ALTSETTING); | ||
412 | if (alt == NULL) { | ||
413 | deb_rc("not alt found!\n"); | ||
414 | return -ENODEV; | ||
415 | } | ||
416 | ret = usb_set_interface(interface_to_usbdev(intf), | ||
417 | alt->desc.bInterfaceNumber, | ||
418 | alt->desc.bAlternateSetting); | ||
419 | if (ret != 0) { | ||
420 | deb_rc("failed to set alt-setting!\n"); | ||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | ret = dvb_usb_device_init(intf, &friio_properties, | ||
425 | THIS_MODULE, &d, adapter_nr); | ||
426 | if (ret == 0) | ||
427 | friio_streaming_ctrl(&d->adapter[0], 1); | ||
428 | |||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | |||
433 | struct jdvbt90502_config friio_fe_config = { | ||
434 | .demod_address = FRIIO_DEMOD_ADDR, | ||
435 | .pll_address = FRIIO_PLL_ADDR, | ||
436 | }; | ||
437 | |||
438 | static struct i2c_algorithm gl861_i2c_algo = { | ||
439 | .master_xfer = gl861_i2c_xfer, | ||
440 | .functionality = gl861_i2c_func, | ||
441 | }; | ||
442 | |||
443 | static struct usb_device_id friio_table[] = { | ||
444 | { USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE) }, | ||
445 | { } /* Terminating entry */ | ||
446 | }; | ||
447 | MODULE_DEVICE_TABLE(usb, friio_table); | ||
448 | |||
449 | |||
450 | static struct dvb_usb_device_properties friio_properties = { | ||
451 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
452 | .usb_ctrl = DEVICE_SPECIFIC, | ||
453 | |||
454 | .size_of_priv = 0, | ||
455 | |||
456 | .num_adapters = 1, | ||
457 | .adapter = { | ||
458 | /* caps:0 => no pid filter, 188B TS packet */ | ||
459 | /* GL861 has a HW pid filter, but no info available. */ | ||
460 | { | ||
461 | .caps = 0, | ||
462 | |||
463 | .frontend_attach = friio_frontend_attach, | ||
464 | .streaming_ctrl = friio_streaming_ctrl, | ||
465 | |||
466 | .stream = { | ||
467 | .type = USB_BULK, | ||
468 | /* count <= MAX_NO_URBS_FOR_DATA_STREAM(10) */ | ||
469 | .count = 8, | ||
470 | .endpoint = 0x01, | ||
471 | .u = { | ||
472 | /* GL861 has 6KB buf inside */ | ||
473 | .bulk = { | ||
474 | .buffersize = 16384, | ||
475 | } | ||
476 | } | ||
477 | }, | ||
478 | } | ||
479 | }, | ||
480 | .i2c_algo = &gl861_i2c_algo, | ||
481 | |||
482 | .num_device_descs = 1, | ||
483 | .devices = { | ||
484 | { | ||
485 | .name = "774 Friio ISDB-T USB2.0", | ||
486 | .cold_ids = { NULL }, | ||
487 | .warm_ids = { &friio_table[0], NULL }, | ||
488 | }, | ||
489 | } | ||
490 | }; | ||
491 | |||
492 | static struct usb_driver friio_driver = { | ||
493 | .name = "dvb_usb_friio", | ||
494 | .probe = friio_probe, | ||
495 | .disconnect = dvb_usb_device_exit, | ||
496 | .id_table = friio_table, | ||
497 | }; | ||
498 | |||
499 | |||
500 | /* module stuff */ | ||
501 | static int __init friio_module_init(void) | ||
502 | { | ||
503 | int ret; | ||
504 | |||
505 | ret = usb_register(&friio_driver); | ||
506 | if (ret) | ||
507 | err("usb_register failed. Error number %d", ret); | ||
508 | |||
509 | return ret; | ||
510 | } | ||
511 | |||
512 | |||
513 | static void __exit friio_module_exit(void) | ||
514 | { | ||
515 | /* deregister this driver from the USB subsystem */ | ||
516 | usb_deregister(&friio_driver); | ||
517 | } | ||
518 | |||
519 | module_init(friio_module_init); | ||
520 | module_exit(friio_module_exit); | ||
521 | |||
522 | MODULE_AUTHOR("Akihiro Tsukada <tskd2@yahoo.co.jp>"); | ||
523 | MODULE_DESCRIPTION("Driver for Friio ISDB-T USB2.0 Receiver"); | ||
524 | MODULE_VERSION("0.2"); | ||
525 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/friio.h b/drivers/media/dvb/dvb-usb/friio.h new file mode 100644 index 000000000000..af8d55e390fb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/friio.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver. | ||
2 | * | ||
3 | * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp> | ||
4 | * | ||
5 | * This module is based off the the gl861 and vp702x modules. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation, version 2. | ||
10 | * | ||
11 | * see Documentation/dvb/README.dvb-usb for more information | ||
12 | */ | ||
13 | #ifndef _DVB_USB_FRIIO_H_ | ||
14 | #define _DVB_USB_FRIIO_H_ | ||
15 | |||
16 | /** | ||
17 | * Friio Components | ||
18 | * USB hub: AU4254 | ||
19 | * USB controller(+ TS dmx & streaming): GL861 | ||
20 | * Frontend: comtech JDVBT-90502 | ||
21 | * (tuner PLL: tua6034, I2C addr:(0xC0 >> 1)) | ||
22 | * (OFDM demodulator: TC90502, I2C addr:(0x30 >> 1)) | ||
23 | * LED x3 (+LNB) controll: PIC 16F676 | ||
24 | * EEPROM: 24C08 | ||
25 | * | ||
26 | * (USB smart card reader: AU9522) | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #define DVB_USB_LOG_PREFIX "friio" | ||
31 | #include "dvb-usb.h" | ||
32 | |||
33 | extern int dvb_usb_friio_debug; | ||
34 | #define deb_info(args...) dprintk(dvb_usb_friio_debug, 0x01, args) | ||
35 | #define deb_xfer(args...) dprintk(dvb_usb_friio_debug, 0x02, args) | ||
36 | #define deb_rc(args...) dprintk(dvb_usb_friio_debug, 0x04, args) | ||
37 | #define deb_fe(args...) dprintk(dvb_usb_friio_debug, 0x08, args) | ||
38 | |||
39 | /* Vendor requests */ | ||
40 | #define GL861_WRITE 0x40 | ||
41 | #define GL861_READ 0xc0 | ||
42 | |||
43 | /* command bytes */ | ||
44 | #define GL861_REQ_I2C_WRITE 0x01 | ||
45 | #define GL861_REQ_I2C_READ 0x02 | ||
46 | /* For control msg with data argument */ | ||
47 | /* Used for accessing the PLL on the secondary I2C bus of FE via GL861 */ | ||
48 | #define GL861_REQ_I2C_DATA_CTRL_WRITE 0x03 | ||
49 | |||
50 | #define GL861_ALTSETTING_COUNT 2 | ||
51 | #define FRIIO_BULK_ALTSETTING 0 | ||
52 | #define FRIIO_ISOC_ALTSETTING 1 | ||
53 | |||
54 | /* LED & LNB control via PIC. */ | ||
55 | /* basically, it's serial control with clock and strobe. */ | ||
56 | /* write the below 4bit control data to the reg 0x00 at the I2C addr 0x00 */ | ||
57 | /* when controlling the LEDs, 32bit(saturation, R, G, B) is sent on the bit3*/ | ||
58 | #define FRIIO_CTL_LNB (1 << 0) | ||
59 | #define FRIIO_CTL_STROBE (1 << 1) | ||
60 | #define FRIIO_CTL_CLK (1 << 2) | ||
61 | #define FRIIO_CTL_LED (1 << 3) | ||
62 | |||
63 | /* Front End related */ | ||
64 | |||
65 | #define FRIIO_DEMOD_ADDR (0x30 >> 1) | ||
66 | #define FRIIO_PLL_ADDR (0xC0 >> 1) | ||
67 | |||
68 | #define JDVBT90502_PLL_CLK 4000000 | ||
69 | #define JDVBT90502_PLL_DIVIDER 28 | ||
70 | |||
71 | #define JDVBT90502_2ND_I2C_REG 0xFE | ||
72 | |||
73 | /* byte index for pll i2c command data structure*/ | ||
74 | /* see datasheet for tua6034 */ | ||
75 | #define DEMOD_REDIRECT_REG 0 | ||
76 | #define ADDRESS_BYTE 1 | ||
77 | #define DIVIDER_BYTE1 2 | ||
78 | #define DIVIDER_BYTE2 3 | ||
79 | #define CONTROL_BYTE 4 | ||
80 | #define BANDSWITCH_BYTE 5 | ||
81 | #define AGC_CTRL_BYTE 5 | ||
82 | #define PLL_CMD_LEN 6 | ||
83 | |||
84 | /* bit masks for PLL STATUS response */ | ||
85 | #define PLL_STATUS_POR_MODE 0x80 /* 1: Power on Reset (test) Mode */ | ||
86 | #define PLL_STATUS_LOCKED 0x40 /* 1: locked */ | ||
87 | #define PLL_STATUS_AGC_ACTIVE 0x08 /* 1:active */ | ||
88 | #define PLL_STATUS_TESTMODE 0x07 /* digital output level (5 level) */ | ||
89 | /* 0.15Vcc step 0x00: < 0.15Vcc, ..., 0x04: >= 0.6Vcc (<= 1Vcc) */ | ||
90 | |||
91 | |||
92 | struct jdvbt90502_config { | ||
93 | u8 demod_address; /* i2c addr for demodulator IC */ | ||
94 | u8 pll_address; /* PLL addr on the secondary i2c*/ | ||
95 | }; | ||
96 | extern struct jdvbt90502_config friio_fe_config; | ||
97 | |||
98 | extern struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d); | ||
99 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index aec7a1943b66..ef9b7bed13ff 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
@@ -337,6 +337,8 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar | |||
337 | int i, pass, ret = 0; | 337 | int i, pass, ret = 0; |
338 | 338 | ||
339 | buff = kmalloc(65536, GFP_KERNEL); | 339 | buff = kmalloc(65536, GFP_KERNEL); |
340 | if (buff == NULL) | ||
341 | return -ENOMEM; | ||
340 | 342 | ||
341 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) | 343 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) |
342 | goto done; | 344 | goto done; |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index b794e860b4e2..d7c4837fa71c 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -484,6 +484,14 @@ config DVB_S921 | |||
484 | AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module. | 484 | AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module. |
485 | Say Y when you want to support this frontend. | 485 | Say Y when you want to support this frontend. |
486 | 486 | ||
487 | config DVB_DIB8000 | ||
488 | tristate "DiBcom 8000MB/MC" | ||
489 | depends on DVB_CORE && I2C | ||
490 | default m if DVB_FE_CUSTOMISE | ||
491 | help | ||
492 | A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator. | ||
493 | Say Y when you want to support this frontend. | ||
494 | |||
487 | comment "Digital terrestrial only tuners/PLL" | 495 | comment "Digital terrestrial only tuners/PLL" |
488 | depends on DVB_CORE | 496 | depends on DVB_CORE |
489 | 497 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 3b49d37ab5fa..3523767e7a76 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o | |||
23 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o | 23 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o |
24 | obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o | 24 | obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o |
25 | obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o | 25 | obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o |
26 | obj-$(CONFIG_DVB_DIB8000) += dib8000.o dibx000_common.o | ||
26 | obj-$(CONFIG_DVB_MT312) += mt312.o | 27 | obj-$(CONFIG_DVB_MT312) += mt312.o |
27 | obj-$(CONFIG_DVB_VES1820) += ves1820.o | 28 | obj-$(CONFIG_DVB_VES1820) += ves1820.o |
28 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o | 29 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o |
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 9e9a75576a1d..74981ee923c8 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c | |||
@@ -792,6 +792,11 @@ static int au8522_probe(struct i2c_client *client, | |||
792 | } | 792 | } |
793 | 793 | ||
794 | demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL); | 794 | demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL); |
795 | if (demod_config == NULL) { | ||
796 | if (instance == 1) | ||
797 | kfree(state); | ||
798 | return -ENOMEM; | ||
799 | } | ||
795 | demod_config->demod_address = 0x8e >> 1; | 800 | demod_config->demod_address = 0x8e >> 1; |
796 | 801 | ||
797 | state->config = demod_config; | 802 | state->config = demod_config; |
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index da92cbe1b8ea..2be17b93e0bd 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c | |||
@@ -1,12 +1,29 @@ | |||
1 | /* | 1 | /* |
2 | * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. | 2 | * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. |
3 | * | 3 | * |
4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) | 4 | * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as | 7 | * modify it under the terms of the GNU General Public License as |
8 | * published by the Free Software Foundation, version 2. | 8 | * published by the Free Software Foundation; either version 2 of the |
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * | ||
22 | * This code is more or less generated from another driver, please | ||
23 | * excuse some codingstyle oddities. | ||
24 | * | ||
9 | */ | 25 | */ |
26 | |||
10 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
11 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
12 | 29 | ||
@@ -19,27 +36,65 @@ static int debug; | |||
19 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 37 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
21 | 38 | ||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0) | 39 | #define dprintk(args...) do { \ |
40 | if (debug) { \ | ||
41 | printk(KERN_DEBUG "DiB0070: "); \ | ||
42 | printk(args); \ | ||
43 | printk("\n"); \ | ||
44 | } \ | ||
45 | } while (0) | ||
23 | 46 | ||
24 | #define DIB0070_P1D 0x00 | 47 | #define DIB0070_P1D 0x00 |
25 | #define DIB0070_P1F 0x01 | 48 | #define DIB0070_P1F 0x01 |
26 | #define DIB0070_P1G 0x03 | 49 | #define DIB0070_P1G 0x03 |
27 | #define DIB0070S_P1A 0x02 | 50 | #define DIB0070S_P1A 0x02 |
28 | 51 | ||
52 | enum frontend_tune_state { | ||
53 | CT_TUNER_START = 10, | ||
54 | CT_TUNER_STEP_0, | ||
55 | CT_TUNER_STEP_1, | ||
56 | CT_TUNER_STEP_2, | ||
57 | CT_TUNER_STEP_3, | ||
58 | CT_TUNER_STEP_4, | ||
59 | CT_TUNER_STEP_5, | ||
60 | CT_TUNER_STEP_6, | ||
61 | CT_TUNER_STEP_7, | ||
62 | CT_TUNER_STOP, | ||
63 | }; | ||
64 | |||
65 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
66 | |||
29 | struct dib0070_state { | 67 | struct dib0070_state { |
30 | struct i2c_adapter *i2c; | 68 | struct i2c_adapter *i2c; |
31 | struct dvb_frontend *fe; | 69 | struct dvb_frontend *fe; |
32 | const struct dib0070_config *cfg; | 70 | const struct dib0070_config *cfg; |
33 | u16 wbd_ff_offset; | 71 | u16 wbd_ff_offset; |
34 | u8 revision; | 72 | u8 revision; |
73 | |||
74 | enum frontend_tune_state tune_state; | ||
75 | u32 current_rf; | ||
76 | |||
77 | /* for the captrim binary search */ | ||
78 | s8 step; | ||
79 | u16 adc_diff; | ||
80 | |||
81 | s8 captrim; | ||
82 | s8 fcaptrim; | ||
83 | u16 lo4; | ||
84 | |||
85 | const struct dib0070_tuning *current_tune_table_index; | ||
86 | const struct dib0070_lna_match *lna_match; | ||
87 | |||
88 | u8 wbd_gain_current; | ||
89 | u16 wbd_offset_3_3[2]; | ||
35 | }; | 90 | }; |
36 | 91 | ||
37 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | 92 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) |
38 | { | 93 | { |
39 | u8 b[2]; | 94 | u8 b[2]; |
40 | struct i2c_msg msg[2] = { | 95 | struct i2c_msg msg[2] = { |
41 | { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, | 96 | {.addr = state->cfg->i2c_address,.flags = 0,.buf = ®,.len = 1}, |
42 | { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, | 97 | {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, |
43 | }; | 98 | }; |
44 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | 99 | if (i2c_transfer(state->i2c, msg, 2) != 2) { |
45 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); | 100 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); |
@@ -51,7 +106,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
51 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | 106 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) |
52 | { | 107 | { |
53 | u8 b[3] = { reg, val >> 8, val & 0xff }; | 108 | u8 b[3] = { reg, val >> 8, val & 0xff }; |
54 | struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; | 109 | struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 }; |
55 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 110 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { |
56 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); | 111 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); |
57 | return -EREMOTEIO; | 112 | return -EREMOTEIO; |
@@ -59,55 +114,71 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | |||
59 | return 0; | 114 | return 0; |
60 | } | 115 | } |
61 | 116 | ||
62 | #define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0) | 117 | #define HARD_RESET(state) do { \ |
118 | state->cfg->sleep(state->fe, 0); \ | ||
119 | if (state->cfg->reset) { \ | ||
120 | state->cfg->reset(state->fe,1); msleep(10); \ | ||
121 | state->cfg->reset(state->fe,0); msleep(10); \ | ||
122 | } \ | ||
123 | } while (0) | ||
63 | 124 | ||
64 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 125 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
65 | { | 126 | { |
66 | struct dib0070_state *st = fe->tuner_priv; | 127 | struct dib0070_state *state = fe->tuner_priv; |
67 | u16 tmp = 0; | 128 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; |
68 | tmp = dib0070_read_reg(st, 0x02) & 0x3fff; | 129 | |
130 | if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000) | ||
131 | tmp |= (0 << 14); | ||
132 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000) | ||
133 | tmp |= (1 << 14); | ||
134 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000) | ||
135 | tmp |= (2 << 14); | ||
136 | else | ||
137 | tmp |= (3 << 14); | ||
69 | 138 | ||
70 | switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) { | 139 | dib0070_write_reg(state, 0x02, tmp); |
71 | case 8000: | 140 | |
72 | tmp |= (0 << 14); | 141 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ |
73 | break; | 142 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { |
74 | case 7000: | 143 | u16 value = dib0070_read_reg(state, 0x17); |
75 | tmp |= (1 << 14); | 144 | |
76 | break; | 145 | dib0070_write_reg(state, 0x17, value & 0xfffc); |
77 | case 6000: | 146 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; |
78 | tmp |= (2 << 14); | 147 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); |
79 | break; | 148 | |
80 | case 5000: | 149 | dib0070_write_reg(state, 0x17, value); |
81 | default: | ||
82 | tmp |= (3 << 14); | ||
83 | break; | ||
84 | } | 150 | } |
85 | dib0070_write_reg(st, 0x02, tmp); | ||
86 | return 0; | 151 | return 0; |
87 | } | 152 | } |
88 | 153 | ||
89 | static void dib0070_captrim(struct dib0070_state *st, u16 LO4) | 154 | static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state) |
90 | { | 155 | { |
91 | int8_t captrim, fcaptrim, step_sign, step; | 156 | int8_t step_sign; |
92 | u16 adc, adc_diff = 3000; | 157 | u16 adc; |
158 | int ret = 0; | ||
93 | 159 | ||
160 | if (*tune_state == CT_TUNER_STEP_0) { | ||
94 | 161 | ||
162 | dib0070_write_reg(state, 0x0f, 0xed10); | ||
163 | dib0070_write_reg(state, 0x17, 0x0034); | ||
95 | 164 | ||
96 | dib0070_write_reg(st, 0x0f, 0xed10); | 165 | dib0070_write_reg(state, 0x18, 0x0032); |
97 | dib0070_write_reg(st, 0x17, 0x0034); | 166 | state->step = state->captrim = state->fcaptrim = 64; |
167 | state->adc_diff = 3000; | ||
168 | ret = 20; | ||
98 | 169 | ||
99 | dib0070_write_reg(st, 0x18, 0x0032); | 170 | *tune_state = CT_TUNER_STEP_1; |
100 | msleep(2); | 171 | } else if (*tune_state == CT_TUNER_STEP_1) { |
172 | state->step /= 2; | ||
173 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); | ||
174 | ret = 15; | ||
101 | 175 | ||
102 | step = captrim = fcaptrim = 64; | 176 | *tune_state = CT_TUNER_STEP_2; |
177 | } else if (*tune_state == CT_TUNER_STEP_2) { | ||
103 | 178 | ||
104 | do { | 179 | adc = dib0070_read_reg(state, 0x19); |
105 | step /= 2; | ||
106 | dib0070_write_reg(st, 0x14, LO4 | captrim); | ||
107 | msleep(1); | ||
108 | adc = dib0070_read_reg(st, 0x19); | ||
109 | 180 | ||
110 | dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024); | 181 | dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024); |
111 | 182 | ||
112 | if (adc >= 400) { | 183 | if (adc >= 400) { |
113 | adc -= 400; | 184 | adc -= 400; |
@@ -117,379 +188,430 @@ static void dib0070_captrim(struct dib0070_state *st, u16 LO4) | |||
117 | step_sign = 1; | 188 | step_sign = 1; |
118 | } | 189 | } |
119 | 190 | ||
120 | if (adc < adc_diff) { | 191 | if (adc < state->adc_diff) { |
121 | dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff); | 192 | dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); |
122 | adc_diff = adc; | 193 | state->adc_diff = adc; |
123 | fcaptrim = captrim; | 194 | state->fcaptrim = state->captrim; |
124 | 195 | ||
196 | } | ||
197 | state->captrim += (step_sign * state->step); | ||
125 | 198 | ||
199 | if (state->step >= 1) | ||
200 | *tune_state = CT_TUNER_STEP_1; | ||
201 | else | ||
202 | *tune_state = CT_TUNER_STEP_3; | ||
126 | 203 | ||
127 | } | 204 | } else if (*tune_state == CT_TUNER_STEP_3) { |
128 | captrim += (step_sign * step); | 205 | dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim); |
129 | } while (step >= 1); | 206 | dib0070_write_reg(state, 0x18, 0x07ff); |
207 | *tune_state = CT_TUNER_STEP_4; | ||
208 | } | ||
130 | 209 | ||
131 | dib0070_write_reg(st, 0x14, LO4 | fcaptrim); | 210 | return ret; |
132 | dib0070_write_reg(st, 0x18, 0x07ff); | ||
133 | } | 211 | } |
134 | 212 | ||
135 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 | 213 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) |
136 | #define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7) | ||
137 | #define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12) | ||
138 | #define LO4_SET_CTRIM(l, c) l |= (c) << 10 | ||
139 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | ||
140 | { | 214 | { |
141 | struct dib0070_state *st = fe->tuner_priv; | 215 | struct dib0070_state *state = fe->tuner_priv; |
142 | u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); | 216 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); |
143 | 217 | dprintk("CTRL_LO5: 0x%x", lo5); | |
144 | u8 band = BAND_OF_FREQUENCY(freq), c; | 218 | return dib0070_write_reg(state, 0x15, lo5); |
219 | } | ||
145 | 220 | ||
146 | /*******************VCO***********************************/ | 221 | void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) |
147 | u16 lo4 = 0; | 222 | { |
223 | struct dib0070_state *state = fe->tuner_priv; | ||
148 | 224 | ||
149 | u8 REFDIV, PRESC = 2; | 225 | if (open) { |
150 | u32 FBDiv, Rest, FREF, VCOF_kHz; | 226 | dib0070_write_reg(state, 0x1b, 0xff00); |
151 | u16 Num, Den; | 227 | dib0070_write_reg(state, 0x1a, 0x0000); |
152 | /*******************FrontEnd******************************/ | 228 | } else { |
153 | u16 value = 0; | 229 | dib0070_write_reg(state, 0x1b, 0x4112); |
230 | if (state->cfg->vga_filter != 0) { | ||
231 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); | ||
232 | dprintk("vga filter register is set to %x", state->cfg->vga_filter); | ||
233 | } else | ||
234 | dib0070_write_reg(state, 0x1a, 0x0009); | ||
235 | } | ||
236 | } | ||
154 | 237 | ||
155 | dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); | 238 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); |
239 | struct dib0070_tuning { | ||
240 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
241 | u8 switch_trim; | ||
242 | u8 vco_band; | ||
243 | u8 hfdiv; | ||
244 | u8 vco_multi; | ||
245 | u8 presc; | ||
246 | u8 wbdmux; | ||
247 | u16 tuner_enable; | ||
248 | }; | ||
156 | 249 | ||
250 | struct dib0070_lna_match { | ||
251 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
252 | u8 lna_band; | ||
253 | }; | ||
157 | 254 | ||
158 | dib0070_write_reg(st, 0x17, 0x30); | 255 | static const struct dib0070_tuning dib0070s_tuning_table[] = { |
256 | {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */ | ||
257 | {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800}, | ||
258 | {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800}, | ||
259 | {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */ | ||
260 | {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | ||
261 | {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | ||
262 | {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */ | ||
263 | }; | ||
159 | 264 | ||
160 | dib0070_set_bandwidth(fe, ch); /* c is used as HF */ | 265 | static const struct dib0070_tuning dib0070_tuning_table[] = { |
161 | switch (st->revision) { | 266 | {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */ |
162 | case DIB0070S_P1A: | 267 | {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */ |
163 | switch (band) { | 268 | {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000}, |
164 | case BAND_LBAND: | 269 | {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000}, |
165 | LO4_SET_VCO_HFDIV(lo4, 1, 1); | 270 | {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */ |
166 | c = 2; | 271 | {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800}, |
167 | break; | 272 | {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800}, |
168 | case BAND_SBAND: | 273 | {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */ |
169 | LO4_SET_VCO_HFDIV(lo4, 0, 0); | 274 | }; |
170 | LO4_SET_CTRIM(lo4, 1); | ||
171 | c = 1; | ||
172 | break; | ||
173 | case BAND_UHF: | ||
174 | default: | ||
175 | if (freq < 570000) { | ||
176 | LO4_SET_VCO_HFDIV(lo4, 1, 3); | ||
177 | PRESC = 6; c = 6; | ||
178 | } else if (freq < 680000) { | ||
179 | LO4_SET_VCO_HFDIV(lo4, 0, 2); | ||
180 | c = 4; | ||
181 | } else { | ||
182 | LO4_SET_VCO_HFDIV(lo4, 1, 2); | ||
183 | c = 4; | ||
184 | } | ||
185 | break; | ||
186 | } break; | ||
187 | |||
188 | case DIB0070_P1G: | ||
189 | case DIB0070_P1F: | ||
190 | default: | ||
191 | switch (band) { | ||
192 | case BAND_FM: | ||
193 | LO4_SET_VCO_HFDIV(lo4, 0, 7); | ||
194 | c = 24; | ||
195 | break; | ||
196 | case BAND_LBAND: | ||
197 | LO4_SET_VCO_HFDIV(lo4, 1, 0); | ||
198 | c = 2; | ||
199 | break; | ||
200 | case BAND_VHF: | ||
201 | if (freq < 180000) { | ||
202 | LO4_SET_VCO_HFDIV(lo4, 0, 3); | ||
203 | c = 16; | ||
204 | } else if (freq < 190000) { | ||
205 | LO4_SET_VCO_HFDIV(lo4, 1, 3); | ||
206 | c = 16; | ||
207 | } else { | ||
208 | LO4_SET_VCO_HFDIV(lo4, 0, 6); | ||
209 | c = 12; | ||
210 | } | ||
211 | break; | ||
212 | |||
213 | case BAND_UHF: | ||
214 | default: | ||
215 | if (freq < 570000) { | ||
216 | LO4_SET_VCO_HFDIV(lo4, 1, 5); | ||
217 | c = 6; | ||
218 | } else if (freq < 700000) { | ||
219 | LO4_SET_VCO_HFDIV(lo4, 0, 1); | ||
220 | c = 4; | ||
221 | } else { | ||
222 | LO4_SET_VCO_HFDIV(lo4, 1, 1); | ||
223 | c = 4; | ||
224 | } | ||
225 | break; | ||
226 | } | ||
227 | break; | ||
228 | } | ||
229 | 275 | ||
230 | dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf); | 276 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { |
231 | dprintk( "VCO = %hd", (lo4 >> 11) & 0x3); | 277 | {180000, 0}, /* VHF */ |
278 | {188000, 1}, | ||
279 | {196400, 2}, | ||
280 | {250000, 3}, | ||
281 | {550000, 0}, /* UHF */ | ||
282 | {590000, 1}, | ||
283 | {666000, 3}, | ||
284 | {864000, 5}, | ||
285 | {1500000, 0}, /* LBAND or everything higher than UHF */ | ||
286 | {1600000, 1}, | ||
287 | {2000000, 3}, | ||
288 | {0xffffffff, 7}, | ||
289 | }; | ||
232 | 290 | ||
291 | static const struct dib0070_lna_match dib0070_lna[] = { | ||
292 | {180000, 0}, /* VHF */ | ||
293 | {188000, 1}, | ||
294 | {196400, 2}, | ||
295 | {250000, 3}, | ||
296 | {550000, 2}, /* UHF */ | ||
297 | {650000, 3}, | ||
298 | {750000, 5}, | ||
299 | {850000, 6}, | ||
300 | {864000, 7}, | ||
301 | {1500000, 0}, /* LBAND or everything higher than UHF */ | ||
302 | {1600000, 1}, | ||
303 | {2000000, 3}, | ||
304 | {0xffffffff, 7}, | ||
305 | }; | ||
233 | 306 | ||
234 | VCOF_kHz = (c * freq) * 2; | 307 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 |
235 | dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq); | 308 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
309 | { | ||
310 | struct dib0070_state *state = fe->tuner_priv; | ||
236 | 311 | ||
237 | switch (band) { | 312 | const struct dib0070_tuning *tune; |
238 | case BAND_VHF: | 313 | const struct dib0070_lna_match *lna_match; |
239 | REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); | ||
240 | break; | ||
241 | case BAND_FM: | ||
242 | REFDIV = (u8) ((st->cfg->clock_khz) / 1000); | ||
243 | break; | ||
244 | default: | ||
245 | REFDIV = (u8) ( st->cfg->clock_khz / 10000); | ||
246 | break; | ||
247 | } | ||
248 | FREF = st->cfg->clock_khz / REFDIV; | ||
249 | 314 | ||
250 | dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); | 315 | enum frontend_tune_state *tune_state = &state->tune_state; |
316 | int ret = 10; /* 1ms is the default delay most of the time */ | ||
251 | 317 | ||
318 | u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); | ||
319 | u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); | ||
252 | 320 | ||
321 | #ifdef CONFIG_SYS_ISDBT | ||
322 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) | ||
323 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) | ||
324 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
325 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
326 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) | ||
327 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
328 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) | ||
329 | freq += 850; | ||
330 | #endif | ||
331 | if (state->current_rf != freq) { | ||
253 | 332 | ||
254 | switch (st->revision) { | 333 | switch (state->revision) { |
255 | case DIB0070S_P1A: | 334 | case DIB0070S_P1A: |
256 | FBDiv = (VCOF_kHz / PRESC / FREF); | 335 | tune = dib0070s_tuning_table; |
257 | Rest = (VCOF_kHz / PRESC) - FBDiv * FREF; | 336 | lna_match = dib0070_lna; |
258 | break; | 337 | break; |
259 | |||
260 | case DIB0070_P1G: | ||
261 | case DIB0070_P1F: | ||
262 | default: | 338 | default: |
263 | FBDiv = (freq / (FREF / 2)); | 339 | tune = dib0070_tuning_table; |
264 | Rest = 2 * freq - FBDiv * FREF; | 340 | if (state->cfg->flip_chip) |
341 | lna_match = dib0070_lna_flip_chip; | ||
342 | else | ||
343 | lna_match = dib0070_lna; | ||
265 | break; | 344 | break; |
266 | } | 345 | } |
267 | 346 | while (freq > tune->max_freq) /* find the right one */ | |
268 | 347 | tune++; | |
269 | if (Rest < LPF) Rest = 0; | 348 | while (freq > lna_match->max_freq) /* find the right one */ |
270 | else if (Rest < 2 * LPF) Rest = 2 * LPF; | 349 | lna_match++; |
271 | else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } | ||
272 | else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; | ||
273 | Rest = (Rest * 6528) / (FREF / 10); | ||
274 | dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); | ||
275 | |||
276 | Num = 0; | ||
277 | Den = 1; | ||
278 | 350 | ||
279 | if (Rest > 0) { | 351 | state->current_tune_table_index = tune; |
280 | LO4_SET_SD(lo4, 1); | 352 | state->lna_match = lna_match; |
281 | Den = 255; | ||
282 | Num = (u16)Rest; | ||
283 | } | 353 | } |
284 | dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1); | ||
285 | 354 | ||
355 | if (*tune_state == CT_TUNER_START) { | ||
356 | dprintk("Tuning for Band: %hd (%d kHz)", band, freq); | ||
357 | if (state->current_rf != freq) { | ||
358 | u8 REFDIV; | ||
359 | u32 FBDiv, Rest, FREF, VCOF_kHz; | ||
360 | u8 Den; | ||
286 | 361 | ||
362 | state->current_rf = freq; | ||
363 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); | ||
287 | 364 | ||
288 | dib0070_write_reg(st, 0x11, (u16)FBDiv); | 365 | dib0070_write_reg(state, 0x17, 0x30); |
289 | 366 | ||
367 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; | ||
290 | 368 | ||
291 | dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); | 369 | switch (band) { |
292 | 370 | case BAND_VHF: | |
371 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); | ||
372 | break; | ||
373 | case BAND_FM: | ||
374 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); | ||
375 | break; | ||
376 | default: | ||
377 | REFDIV = (u8) (state->cfg->clock_khz / 10000); | ||
378 | break; | ||
379 | } | ||
380 | FREF = state->cfg->clock_khz / REFDIV; | ||
381 | |||
382 | switch (state->revision) { | ||
383 | case DIB0070S_P1A: | ||
384 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); | ||
385 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; | ||
386 | break; | ||
387 | |||
388 | case DIB0070_P1G: | ||
389 | case DIB0070_P1F: | ||
390 | default: | ||
391 | FBDiv = (freq / (FREF / 2)); | ||
392 | Rest = 2 * freq - FBDiv * FREF; | ||
393 | break; | ||
394 | } | ||
293 | 395 | ||
294 | dib0070_write_reg(st, 0x13, Num); | 396 | if (Rest < LPF) |
397 | Rest = 0; | ||
398 | else if (Rest < 2 * LPF) | ||
399 | Rest = 2 * LPF; | ||
400 | else if (Rest > (FREF - LPF)) { | ||
401 | Rest = 0; | ||
402 | FBDiv += 1; | ||
403 | } else if (Rest > (FREF - 2 * LPF)) | ||
404 | Rest = FREF - 2 * LPF; | ||
405 | Rest = (Rest * 6528) / (FREF / 10); | ||
406 | |||
407 | Den = 1; | ||
408 | if (Rest > 0) { | ||
409 | state->lo4 |= (1 << 14) | (1 << 12); | ||
410 | Den = 255; | ||
411 | } | ||
295 | 412 | ||
413 | dib0070_write_reg(state, 0x11, (u16) FBDiv); | ||
414 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); | ||
415 | dib0070_write_reg(state, 0x13, (u16) Rest); | ||
296 | 416 | ||
297 | value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001; | 417 | if (state->revision == DIB0070S_P1A) { |
298 | 418 | ||
299 | switch (band) { | 419 | if (band == BAND_SBAND) { |
300 | case BAND_UHF: value |= 0x4000 | 0x0800; break; | 420 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
301 | case BAND_LBAND: value |= 0x2000 | 0x0400; break; | 421 | dib0070_write_reg(state, 0x1d, 0xFFFF); |
302 | default: value |= 0x8000 | 0x1000; break; | 422 | } else |
303 | } | 423 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); |
304 | dib0070_write_reg(st, 0x20, value); | 424 | } |
305 | 425 | ||
306 | dib0070_captrim(st, lo4); | 426 | dib0070_write_reg(state, 0x20, |
307 | if (st->revision == DIB0070S_P1A) { | 427 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); |
308 | if (band == BAND_SBAND) | ||
309 | dib0070_write_reg(st, 0x15, 0x16e2); | ||
310 | else | ||
311 | dib0070_write_reg(st, 0x15, 0x56e5); | ||
312 | } | ||
313 | 428 | ||
429 | dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); | ||
430 | dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); | ||
431 | dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); | ||
432 | dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); | ||
433 | dprintk("VCO = %hd", state->current_tune_table_index->vco_band); | ||
434 | dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); | ||
314 | 435 | ||
436 | *tune_state = CT_TUNER_STEP_0; | ||
437 | } else { /* we are already tuned to this frequency - the configuration is correct */ | ||
438 | ret = 50; /* wakeup time */ | ||
439 | *tune_state = CT_TUNER_STEP_5; | ||
440 | } | ||
441 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { | ||
442 | |||
443 | ret = dib0070_captrim(state, tune_state); | ||
444 | |||
445 | } else if (*tune_state == CT_TUNER_STEP_4) { | ||
446 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | ||
447 | if (tmp != NULL) { | ||
448 | while (freq / 1000 > tmp->freq) /* find the right one */ | ||
449 | tmp++; | ||
450 | dib0070_write_reg(state, 0x0f, | ||
451 | (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> | ||
452 | current_tune_table_index-> | ||
453 | wbdmux << 0)); | ||
454 | state->wbd_gain_current = tmp->wbd_gain_val; | ||
455 | } else { | ||
456 | dib0070_write_reg(state, 0x0f, | ||
457 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> | ||
458 | wbdmux << 0)); | ||
459 | state->wbd_gain_current = 6; | ||
460 | } | ||
315 | 461 | ||
316 | switch (band) { | 462 | dib0070_write_reg(state, 0x06, 0x3fff); |
317 | case BAND_UHF: value = 0x7c82; break; | 463 | dib0070_write_reg(state, 0x07, |
318 | case BAND_LBAND: value = 0x7c84; break; | 464 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); |
319 | default: value = 0x7c81; break; | 465 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); |
320 | } | 466 | dib0070_write_reg(state, 0x0d, 0x0d80); |
321 | dib0070_write_reg(st, 0x0f, value); | 467 | |
322 | dib0070_write_reg(st, 0x06, 0x3fff); | 468 | dib0070_write_reg(state, 0x18, 0x07ff); |
323 | 469 | dib0070_write_reg(state, 0x17, 0x0033); | |
324 | /* Front End */ | 470 | |
325 | /* c == TUNE, value = SWITCH */ | 471 | *tune_state = CT_TUNER_STEP_5; |
326 | c = 0; | 472 | } else if (*tune_state == CT_TUNER_STEP_5) { |
327 | value = 0; | 473 | dib0070_set_bandwidth(fe, ch); |
328 | switch (band) { | 474 | *tune_state = CT_TUNER_STOP; |
329 | case BAND_FM: | 475 | } else { |
330 | c = 0; value = 1; | 476 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ |
331 | break; | ||
332 | |||
333 | case BAND_VHF: | ||
334 | if (freq <= 180000) c = 0; | ||
335 | else if (freq <= 188200) c = 1; | ||
336 | else if (freq <= 196400) c = 2; | ||
337 | else c = 3; | ||
338 | value = 1; | ||
339 | break; | ||
340 | |||
341 | case BAND_LBAND: | ||
342 | if (freq <= 1500000) c = 0; | ||
343 | else if (freq <= 1600000) c = 1; | ||
344 | else c = 3; | ||
345 | break; | ||
346 | |||
347 | case BAND_SBAND: | ||
348 | c = 7; | ||
349 | dib0070_write_reg(st, 0x1d,0xFFFF); | ||
350 | break; | ||
351 | |||
352 | case BAND_UHF: | ||
353 | default: | ||
354 | if (st->cfg->flip_chip) { | ||
355 | if (freq <= 550000) c = 0; | ||
356 | else if (freq <= 590000) c = 1; | ||
357 | else if (freq <= 666000) c = 3; | ||
358 | else c = 5; | ||
359 | } else { | ||
360 | if (freq <= 550000) c = 2; | ||
361 | else if (freq <= 650000) c = 3; | ||
362 | else if (freq <= 750000) c = 5; | ||
363 | else if (freq <= 850000) c = 6; | ||
364 | else c = 7; | ||
365 | } | ||
366 | value = 2; | ||
367 | break; | ||
368 | } | 477 | } |
478 | return ret; | ||
479 | } | ||
369 | 480 | ||
370 | /* default: LNA_MATCH=7, BIAS=3 */ | 481 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) |
371 | dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0)); | 482 | { |
372 | dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127)); | 483 | struct dib0070_state *state = fe->tuner_priv; |
373 | dib0070_write_reg(st, 0x0d, 0x0d80); | 484 | uint32_t ret; |
374 | 485 | ||
486 | state->tune_state = CT_TUNER_START; | ||
375 | 487 | ||
376 | dib0070_write_reg(st, 0x18, 0x07ff); | 488 | do { |
377 | dib0070_write_reg(st, 0x17, 0x0033); | 489 | ret = dib0070_tune_digital(fe, p); |
490 | if (ret != FE_CALLBACK_TIME_NEVER) | ||
491 | msleep(ret / 10); | ||
492 | else | ||
493 | break; | ||
494 | } while (state->tune_state != CT_TUNER_STOP); | ||
378 | 495 | ||
379 | return 0; | 496 | return 0; |
380 | } | 497 | } |
381 | 498 | ||
382 | static int dib0070_wakeup(struct dvb_frontend *fe) | 499 | static int dib0070_wakeup(struct dvb_frontend *fe) |
383 | { | 500 | { |
384 | struct dib0070_state *st = fe->tuner_priv; | 501 | struct dib0070_state *state = fe->tuner_priv; |
385 | if (st->cfg->sleep) | 502 | if (state->cfg->sleep) |
386 | st->cfg->sleep(fe, 0); | 503 | state->cfg->sleep(fe, 0); |
387 | return 0; | 504 | return 0; |
388 | } | 505 | } |
389 | 506 | ||
390 | static int dib0070_sleep(struct dvb_frontend *fe) | 507 | static int dib0070_sleep(struct dvb_frontend *fe) |
391 | { | 508 | { |
392 | struct dib0070_state *st = fe->tuner_priv; | 509 | struct dib0070_state *state = fe->tuner_priv; |
393 | if (st->cfg->sleep) | 510 | if (state->cfg->sleep) |
394 | st->cfg->sleep(fe, 1); | 511 | state->cfg->sleep(fe, 1); |
395 | return 0; | 512 | return 0; |
396 | } | 513 | } |
397 | 514 | ||
398 | static u16 dib0070_p1f_defaults[] = | 515 | static const u16 dib0070_p1f_defaults[] = { |
399 | |||
400 | { | ||
401 | 7, 0x02, | 516 | 7, 0x02, |
402 | 0x0008, | 517 | 0x0008, |
403 | 0x0000, | 518 | 0x0000, |
404 | 0x0000, | 519 | 0x0000, |
405 | 0x0000, | 520 | 0x0000, |
406 | 0x0000, | 521 | 0x0000, |
407 | 0x0002, | 522 | 0x0002, |
408 | 0x0100, | 523 | 0x0100, |
409 | 524 | ||
410 | 3, 0x0d, | 525 | 3, 0x0d, |
411 | 0x0d80, | 526 | 0x0d80, |
412 | 0x0001, | 527 | 0x0001, |
413 | 0x0000, | 528 | 0x0000, |
414 | 529 | ||
415 | 4, 0x11, | 530 | 4, 0x11, |
416 | 0x0000, | 531 | 0x0000, |
417 | 0x0103, | 532 | 0x0103, |
418 | 0x0000, | 533 | 0x0000, |
419 | 0x0000, | 534 | 0x0000, |
420 | 535 | ||
421 | 3, 0x16, | 536 | 3, 0x16, |
422 | 0x0004 | 0x0040, | 537 | 0x0004 | 0x0040, |
423 | 0x0030, | 538 | 0x0030, |
424 | 0x07ff, | 539 | 0x07ff, |
425 | 540 | ||
426 | 6, 0x1b, | 541 | 6, 0x1b, |
427 | 0x4112, | 542 | 0x4112, |
428 | 0xff00, | 543 | 0xff00, |
429 | 0xc07f, | 544 | 0xc07f, |
430 | 0x0000, | 545 | 0x0000, |
431 | 0x0180, | 546 | 0x0180, |
432 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, | 547 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, |
433 | 548 | ||
434 | 0, | 549 | 0, |
435 | }; | 550 | }; |
436 | 551 | ||
437 | static void dib0070_wbd_calibration(struct dvb_frontend *fe) | 552 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) |
438 | { | 553 | { |
439 | u16 wbd_offs; | 554 | u16 tuner_en = dib0070_read_reg(state, 0x20); |
440 | struct dib0070_state *state = fe->tuner_priv; | 555 | u16 offset; |
441 | |||
442 | if (state->cfg->sleep) | ||
443 | state->cfg->sleep(fe, 0); | ||
444 | 556 | ||
445 | dib0070_write_reg(state, 0x0f, 0x6d81); | 557 | dib0070_write_reg(state, 0x18, 0x07ff); |
446 | dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); | 558 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); |
559 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); | ||
447 | msleep(9); | 560 | msleep(9); |
448 | wbd_offs = dib0070_read_reg(state, 0x19); | 561 | offset = dib0070_read_reg(state, 0x19); |
449 | dib0070_write_reg(state, 0x20, 0); | 562 | dib0070_write_reg(state, 0x20, tuner_en); |
450 | state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2); | 563 | return offset; |
451 | dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset); | ||
452 | |||
453 | if (state->cfg->sleep) | ||
454 | state->cfg->sleep(fe, 1); | ||
455 | |||
456 | } | 564 | } |
457 | 565 | ||
458 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 566 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) |
459 | { | 567 | { |
460 | struct dib0070_state *st = fe->tuner_priv; | 568 | u8 gain; |
461 | return st->wbd_ff_offset; | 569 | for (gain = 6; gain < 8; gain++) { |
570 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); | ||
571 | dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]); | ||
572 | } | ||
462 | } | 573 | } |
463 | 574 | ||
464 | EXPORT_SYMBOL(dib0070_wbd_offset); | 575 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
465 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) | ||
466 | { | 576 | { |
467 | struct dib0070_state *state = fe->tuner_priv; | 577 | struct dib0070_state *state = fe->tuner_priv; |
468 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); | 578 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; |
469 | dprintk( "CTRL_LO5: 0x%x", lo5); | 579 | u32 freq = fe->dtv_property_cache.frequency / 1000; |
470 | return dib0070_write_reg(state, 0x15, lo5); | 580 | |
581 | if (tmp != NULL) { | ||
582 | while (freq / 1000 > tmp->freq) /* find the right one */ | ||
583 | tmp++; | ||
584 | state->wbd_gain_current = tmp->wbd_gain_val; | ||
585 | } else | ||
586 | state->wbd_gain_current = 6; | ||
587 | |||
588 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; | ||
471 | } | 589 | } |
472 | 590 | ||
591 | EXPORT_SYMBOL(dib0070_wbd_offset); | ||
592 | |||
473 | #define pgm_read_word(w) (*w) | 593 | #define pgm_read_word(w) (*w) |
474 | static int dib0070_reset(struct dib0070_state *state) | 594 | static int dib0070_reset(struct dvb_frontend *fe) |
475 | { | 595 | { |
596 | struct dib0070_state *state = fe->tuner_priv; | ||
476 | u16 l, r, *n; | 597 | u16 l, r, *n; |
477 | 598 | ||
478 | HARD_RESET(state); | 599 | HARD_RESET(state); |
479 | 600 | ||
480 | |||
481 | #ifndef FORCE_SBAND_TUNER | 601 | #ifndef FORCE_SBAND_TUNER |
482 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) | 602 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) |
483 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; | 603 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; |
484 | else | 604 | else |
605 | #else | ||
606 | #warning forcing SBAND | ||
485 | #endif | 607 | #endif |
486 | state->revision = DIB0070S_P1A; | 608 | state->revision = DIB0070S_P1A; |
487 | 609 | ||
488 | /* P1F or not */ | 610 | /* P1F or not */ |
489 | dprintk( "Revision: %x", state->revision); | 611 | dprintk("Revision: %x", state->revision); |
490 | 612 | ||
491 | if (state->revision == DIB0070_P1D) { | 613 | if (state->revision == DIB0070_P1D) { |
492 | dprintk( "Error: this driver is not to be used meant for P1D or earlier"); | 614 | dprintk("Error: this driver is not to be used meant for P1D or earlier"); |
493 | return -EINVAL; | 615 | return -EINVAL; |
494 | } | 616 | } |
495 | 617 | ||
@@ -498,7 +620,7 @@ static int dib0070_reset(struct dib0070_state *state) | |||
498 | while (l) { | 620 | while (l) { |
499 | r = pgm_read_word(n++); | 621 | r = pgm_read_word(n++); |
500 | do { | 622 | do { |
501 | dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); | 623 | dib0070_write_reg(state, (u8) r, pgm_read_word(n++)); |
502 | r++; | 624 | r++; |
503 | } while (--l); | 625 | } while (--l); |
504 | l = pgm_read_word(n++); | 626 | l = pgm_read_word(n++); |
@@ -514,24 +636,25 @@ static int dib0070_reset(struct dib0070_state *state) | |||
514 | r |= state->cfg->osc_buffer_state << 3; | 636 | r |= state->cfg->osc_buffer_state << 3; |
515 | 637 | ||
516 | dib0070_write_reg(state, 0x10, r); | 638 | dib0070_write_reg(state, 0x10, r); |
517 | dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4)); | 639 | dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5)); |
518 | 640 | ||
519 | if (state->cfg->invert_iq) { | 641 | if (state->cfg->invert_iq) { |
520 | r = dib0070_read_reg(state, 0x02) & 0xffdf; | 642 | r = dib0070_read_reg(state, 0x02) & 0xffdf; |
521 | dib0070_write_reg(state, 0x02, r | (1 << 5)); | 643 | dib0070_write_reg(state, 0x02, r | (1 << 5)); |
522 | } | 644 | } |
523 | 645 | ||
524 | |||
525 | if (state->revision == DIB0070S_P1A) | 646 | if (state->revision == DIB0070S_P1A) |
526 | dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1); | 647 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
527 | else | 648 | else |
528 | dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0); | 649 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); |
529 | 650 | ||
530 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); | 651 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); |
652 | |||
653 | dib0070_wbd_offset_calibration(state); | ||
654 | |||
531 | return 0; | 655 | return 0; |
532 | } | 656 | } |
533 | 657 | ||
534 | |||
535 | static int dib0070_release(struct dvb_frontend *fe) | 658 | static int dib0070_release(struct dvb_frontend *fe) |
536 | { | 659 | { |
537 | kfree(fe->tuner_priv); | 660 | kfree(fe->tuner_priv); |
@@ -539,23 +662,24 @@ static int dib0070_release(struct dvb_frontend *fe) | |||
539 | return 0; | 662 | return 0; |
540 | } | 663 | } |
541 | 664 | ||
542 | static struct dvb_tuner_ops dib0070_ops = { | 665 | static const struct dvb_tuner_ops dib0070_ops = { |
543 | .info = { | 666 | .info = { |
544 | .name = "DiBcom DiB0070", | 667 | .name = "DiBcom DiB0070", |
545 | .frequency_min = 45000000, | 668 | .frequency_min = 45000000, |
546 | .frequency_max = 860000000, | 669 | .frequency_max = 860000000, |
547 | .frequency_step = 1000, | 670 | .frequency_step = 1000, |
548 | }, | 671 | }, |
549 | .release = dib0070_release, | 672 | .release = dib0070_release, |
550 | 673 | ||
551 | .init = dib0070_wakeup, | 674 | .init = dib0070_wakeup, |
552 | .sleep = dib0070_sleep, | 675 | .sleep = dib0070_sleep, |
553 | .set_params = dib0070_tune_digital, | 676 | .set_params = dib0070_tune, |
554 | // .get_frequency = dib0070_get_frequency, | 677 | |
555 | // .get_bandwidth = dib0070_get_bandwidth | 678 | // .get_frequency = dib0070_get_frequency, |
679 | // .get_bandwidth = dib0070_get_bandwidth | ||
556 | }; | 680 | }; |
557 | 681 | ||
558 | struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | 682 | struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) |
559 | { | 683 | { |
560 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); | 684 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); |
561 | if (state == NULL) | 685 | if (state == NULL) |
@@ -563,25 +687,24 @@ struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
563 | 687 | ||
564 | state->cfg = cfg; | 688 | state->cfg = cfg; |
565 | state->i2c = i2c; | 689 | state->i2c = i2c; |
566 | state->fe = fe; | 690 | state->fe = fe; |
567 | fe->tuner_priv = state; | 691 | fe->tuner_priv = state; |
568 | 692 | ||
569 | if (dib0070_reset(state) != 0) | 693 | if (dib0070_reset(fe) != 0) |
570 | goto free_mem; | 694 | goto free_mem; |
571 | 695 | ||
572 | dib0070_wbd_calibration(fe); | ||
573 | |||
574 | printk(KERN_INFO "DiB0070: successfully identified\n"); | 696 | printk(KERN_INFO "DiB0070: successfully identified\n"); |
575 | memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); | 697 | memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); |
576 | 698 | ||
577 | fe->tuner_priv = state; | 699 | fe->tuner_priv = state; |
578 | return fe; | 700 | return fe; |
579 | 701 | ||
580 | free_mem: | 702 | free_mem: |
581 | kfree(state); | 703 | kfree(state); |
582 | fe->tuner_priv = NULL; | 704 | fe->tuner_priv = NULL; |
583 | return NULL; | 705 | return NULL; |
584 | } | 706 | } |
707 | |||
585 | EXPORT_SYMBOL(dib0070_attach); | 708 | EXPORT_SYMBOL(dib0070_attach); |
586 | 709 | ||
587 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 710 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index 9670f5d20cfb..8a2e1e710adb 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h | |||
@@ -15,6 +15,11 @@ struct i2c_adapter; | |||
15 | 15 | ||
16 | #define DEFAULT_DIB0070_I2C_ADDRESS 0x60 | 16 | #define DEFAULT_DIB0070_I2C_ADDRESS 0x60 |
17 | 17 | ||
18 | struct dib0070_wbd_gain_cfg { | ||
19 | u16 freq; | ||
20 | u16 wbd_gain_val; | ||
21 | }; | ||
22 | |||
18 | struct dib0070_config { | 23 | struct dib0070_config { |
19 | u8 i2c_address; | 24 | u8 i2c_address; |
20 | 25 | ||
@@ -26,26 +31,28 @@ struct dib0070_config { | |||
26 | int freq_offset_khz_uhf; | 31 | int freq_offset_khz_uhf; |
27 | int freq_offset_khz_vhf; | 32 | int freq_offset_khz_vhf; |
28 | 33 | ||
29 | u8 osc_buffer_state; /* 0= normal, 1= tri-state */ | 34 | u8 osc_buffer_state; /* 0= normal, 1= tri-state */ |
30 | u32 clock_khz; | 35 | u32 clock_khz; |
31 | u8 clock_pad_drive; /* (Drive + 1) * 2mA */ | 36 | u8 clock_pad_drive; /* (Drive + 1) * 2mA */ |
32 | 37 | ||
33 | u8 invert_iq; /* invert Q - in case I or Q is inverted on the board */ | 38 | u8 invert_iq; /* invert Q - in case I or Q is inverted on the board */ |
34 | 39 | ||
35 | u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ | 40 | u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ |
36 | 41 | ||
37 | u8 flip_chip; | 42 | u8 flip_chip; |
43 | u8 enable_third_order_filter; | ||
44 | u8 charge_pump; | ||
45 | |||
46 | const struct dib0070_wbd_gain_cfg *wbd_gain; | ||
47 | |||
48 | u8 vga_filter; | ||
38 | }; | 49 | }; |
39 | 50 | ||
40 | #if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE)) | 51 | #if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE)) |
41 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, | 52 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); |
42 | struct i2c_adapter *i2c, | ||
43 | struct dib0070_config *cfg); | ||
44 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); | 53 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); |
45 | #else | 54 | #else |
46 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, | 55 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) |
47 | struct i2c_adapter *i2c, | ||
48 | struct dib0070_config *cfg) | ||
49 | { | 56 | { |
50 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 57 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
51 | return NULL; | 58 | return NULL; |
@@ -57,5 +64,6 @@ static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) | |||
57 | return -ENODEV; | 64 | return -ENODEV; |
58 | } | 65 | } |
59 | #endif | 66 | #endif |
67 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); | ||
60 | 68 | ||
61 | #endif | 69 | #endif |
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index fc96fbf03d6d..55ef6eeb0769 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/i2c.h> | 11 | #include <linux/i2c.h> |
12 | 12 | ||
13 | #include "dvb_math.h" | ||
13 | #include "dvb_frontend.h" | 14 | #include "dvb_frontend.h" |
14 | 15 | ||
15 | #include "dib7000p.h" | 16 | #include "dib7000p.h" |
@@ -1217,7 +1218,37 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | |||
1217 | 1218 | ||
1218 | static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) | 1219 | static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) |
1219 | { | 1220 | { |
1220 | *snr = 0x0000; | 1221 | struct dib7000p_state *state = fe->demodulator_priv; |
1222 | u16 val; | ||
1223 | s32 signal_mant, signal_exp, noise_mant, noise_exp; | ||
1224 | u32 result = 0; | ||
1225 | |||
1226 | val = dib7000p_read_word(state, 479); | ||
1227 | noise_mant = (val >> 4) & 0xff; | ||
1228 | noise_exp = ((val & 0xf) << 2); | ||
1229 | val = dib7000p_read_word(state, 480); | ||
1230 | noise_exp += ((val >> 14) & 0x3); | ||
1231 | if ((noise_exp & 0x20) != 0) | ||
1232 | noise_exp -= 0x40; | ||
1233 | |||
1234 | signal_mant = (val >> 6) & 0xFF; | ||
1235 | signal_exp = (val & 0x3F); | ||
1236 | if ((signal_exp & 0x20) != 0) | ||
1237 | signal_exp -= 0x40; | ||
1238 | |||
1239 | if (signal_mant != 0) | ||
1240 | result = intlog10(2) * 10 * signal_exp + 10 * | ||
1241 | intlog10(signal_mant); | ||
1242 | else | ||
1243 | result = intlog10(2) * 10 * signal_exp - 100; | ||
1244 | |||
1245 | if (noise_mant != 0) | ||
1246 | result -= intlog10(2) * 10 * noise_exp + 10 * | ||
1247 | intlog10(noise_mant); | ||
1248 | else | ||
1249 | result -= intlog10(2) * 10 * noise_exp - 100; | ||
1250 | |||
1251 | *snr = result / ((1 << 24) / 10); | ||
1221 | return 0; | 1252 | return 0; |
1222 | } | 1253 | } |
1223 | 1254 | ||
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c new file mode 100644 index 000000000000..852c790d09d9 --- /dev/null +++ b/drivers/media/dvb/frontends/dib8000.c | |||
@@ -0,0 +1,2277 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T). | ||
3 | * | ||
4 | * Copyright (C) 2009 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/i2c.h> | ||
12 | #include "dvb_math.h" | ||
13 | |||
14 | #include "dvb_frontend.h" | ||
15 | |||
16 | #include "dib8000.h" | ||
17 | |||
18 | #define LAYER_ALL -1 | ||
19 | #define LAYER_A 1 | ||
20 | #define LAYER_B 2 | ||
21 | #define LAYER_C 3 | ||
22 | |||
23 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
24 | |||
25 | static int debug; | ||
26 | module_param(debug, int, 0644); | ||
27 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
28 | |||
29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) | ||
30 | |||
31 | enum frontend_tune_state { | ||
32 | CT_AGC_START = 20, | ||
33 | CT_AGC_STEP_0, | ||
34 | CT_AGC_STEP_1, | ||
35 | CT_AGC_STEP_2, | ||
36 | CT_AGC_STEP_3, | ||
37 | CT_AGC_STEP_4, | ||
38 | CT_AGC_STOP, | ||
39 | |||
40 | CT_DEMOD_START = 30, | ||
41 | }; | ||
42 | |||
43 | #define FE_STATUS_TUNE_FAILED 0 | ||
44 | |||
45 | struct i2c_device { | ||
46 | struct i2c_adapter *adap; | ||
47 | u8 addr; | ||
48 | }; | ||
49 | |||
50 | struct dib8000_state { | ||
51 | struct dvb_frontend fe; | ||
52 | struct dib8000_config cfg; | ||
53 | |||
54 | struct i2c_device i2c; | ||
55 | |||
56 | struct dibx000_i2c_master i2c_master; | ||
57 | |||
58 | u16 wbd_ref; | ||
59 | |||
60 | u8 current_band; | ||
61 | u32 current_bandwidth; | ||
62 | struct dibx000_agc_config *current_agc; | ||
63 | u32 timf; | ||
64 | u32 timf_default; | ||
65 | |||
66 | u8 div_force_off:1; | ||
67 | u8 div_state:1; | ||
68 | u16 div_sync_wait; | ||
69 | |||
70 | u8 agc_state; | ||
71 | u8 differential_constellation; | ||
72 | u8 diversity_onoff; | ||
73 | |||
74 | s16 ber_monitored_layer; | ||
75 | u16 gpio_dir; | ||
76 | u16 gpio_val; | ||
77 | |||
78 | u16 revision; | ||
79 | u8 isdbt_cfg_loaded; | ||
80 | enum frontend_tune_state tune_state; | ||
81 | u32 status; | ||
82 | }; | ||
83 | |||
84 | enum dib8000_power_mode { | ||
85 | DIB8000M_POWER_ALL = 0, | ||
86 | DIB8000M_POWER_INTERFACE_ONLY, | ||
87 | }; | ||
88 | |||
89 | static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) | ||
90 | { | ||
91 | u8 wb[2] = { reg >> 8, reg & 0xff }; | ||
92 | u8 rb[2]; | ||
93 | struct i2c_msg msg[2] = { | ||
94 | {.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2}, | ||
95 | {.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2}, | ||
96 | }; | ||
97 | |||
98 | if (i2c_transfer(i2c->adap, msg, 2) != 2) | ||
99 | dprintk("i2c read error on %d", reg); | ||
100 | |||
101 | return (rb[0] << 8) | rb[1]; | ||
102 | } | ||
103 | |||
104 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | ||
105 | { | ||
106 | return dib8000_i2c_read16(&state->i2c, reg); | ||
107 | } | ||
108 | |||
109 | static u32 dib8000_read32(struct dib8000_state *state, u16 reg) | ||
110 | { | ||
111 | u16 rw[2]; | ||
112 | |||
113 | rw[0] = dib8000_read_word(state, reg + 0); | ||
114 | rw[1] = dib8000_read_word(state, reg + 1); | ||
115 | |||
116 | return ((rw[0] << 16) | (rw[1])); | ||
117 | } | ||
118 | |||
119 | static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) | ||
120 | { | ||
121 | u8 b[4] = { | ||
122 | (reg >> 8) & 0xff, reg & 0xff, | ||
123 | (val >> 8) & 0xff, val & 0xff, | ||
124 | }; | ||
125 | struct i2c_msg msg = { | ||
126 | .addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4 | ||
127 | }; | ||
128 | return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
129 | } | ||
130 | |||
131 | static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) | ||
132 | { | ||
133 | return dib8000_i2c_write16(&state->i2c, reg, val); | ||
134 | } | ||
135 | |||
136 | const int16_t coeff_2k_sb_1seg_dqpsk[8] = { | ||
137 | (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, | ||
138 | (920 << 5) | 0x09 | ||
139 | }; | ||
140 | |||
141 | const int16_t coeff_2k_sb_1seg[8] = { | ||
142 | (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f | ||
143 | }; | ||
144 | |||
145 | const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
146 | (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, | ||
147 | (-931 << 5) | 0x0f | ||
148 | }; | ||
149 | |||
150 | const int16_t coeff_2k_sb_3seg_0dqpsk[8] = { | ||
151 | (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, | ||
152 | (982 << 5) | 0x0c | ||
153 | }; | ||
154 | |||
155 | const int16_t coeff_2k_sb_3seg_1dqpsk[8] = { | ||
156 | (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, | ||
157 | (-720 << 5) | 0x0d | ||
158 | }; | ||
159 | |||
160 | const int16_t coeff_2k_sb_3seg[8] = { | ||
161 | (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, | ||
162 | (-610 << 5) | 0x0a | ||
163 | }; | ||
164 | |||
165 | const int16_t coeff_4k_sb_1seg_dqpsk[8] = { | ||
166 | (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, | ||
167 | (-922 << 5) | 0x0d | ||
168 | }; | ||
169 | |||
170 | const int16_t coeff_4k_sb_1seg[8] = { | ||
171 | (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, | ||
172 | (-655 << 5) | 0x0a | ||
173 | }; | ||
174 | |||
175 | const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
176 | (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, | ||
177 | (-958 << 5) | 0x13 | ||
178 | }; | ||
179 | |||
180 | const int16_t coeff_4k_sb_3seg_0dqpsk[8] = { | ||
181 | (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, | ||
182 | (-568 << 5) | 0x0f | ||
183 | }; | ||
184 | |||
185 | const int16_t coeff_4k_sb_3seg_1dqpsk[8] = { | ||
186 | (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, | ||
187 | (-848 << 5) | 0x13 | ||
188 | }; | ||
189 | |||
190 | const int16_t coeff_4k_sb_3seg[8] = { | ||
191 | (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, | ||
192 | (-869 << 5) | 0x13 | ||
193 | }; | ||
194 | |||
195 | const int16_t coeff_8k_sb_1seg_dqpsk[8] = { | ||
196 | (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, | ||
197 | (-598 << 5) | 0x10 | ||
198 | }; | ||
199 | |||
200 | const int16_t coeff_8k_sb_1seg[8] = { | ||
201 | (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, | ||
202 | (585 << 5) | 0x0f | ||
203 | }; | ||
204 | |||
205 | const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
206 | (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, | ||
207 | (0 << 5) | 0x14 | ||
208 | }; | ||
209 | |||
210 | const int16_t coeff_8k_sb_3seg_0dqpsk[8] = { | ||
211 | (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, | ||
212 | (-877 << 5) | 0x15 | ||
213 | }; | ||
214 | |||
215 | const int16_t coeff_8k_sb_3seg_1dqpsk[8] = { | ||
216 | (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, | ||
217 | (-921 << 5) | 0x14 | ||
218 | }; | ||
219 | |||
220 | const int16_t coeff_8k_sb_3seg[8] = { | ||
221 | (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, | ||
222 | (690 << 5) | 0x14 | ||
223 | }; | ||
224 | |||
225 | const int16_t ana_fe_coeff_3seg[24] = { | ||
226 | 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 | ||
227 | }; | ||
228 | |||
229 | const int16_t ana_fe_coeff_1seg[24] = { | ||
230 | 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 | ||
231 | }; | ||
232 | |||
233 | const int16_t ana_fe_coeff_13seg[24] = { | ||
234 | 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 | ||
235 | }; | ||
236 | |||
237 | static u16 fft_to_mode(struct dib8000_state *state) | ||
238 | { | ||
239 | u16 mode; | ||
240 | switch (state->fe.dtv_property_cache.transmission_mode) { | ||
241 | case TRANSMISSION_MODE_2K: | ||
242 | mode = 1; | ||
243 | break; | ||
244 | case TRANSMISSION_MODE_4K: | ||
245 | mode = 2; | ||
246 | break; | ||
247 | default: | ||
248 | case TRANSMISSION_MODE_AUTO: | ||
249 | case TRANSMISSION_MODE_8K: | ||
250 | mode = 3; | ||
251 | break; | ||
252 | } | ||
253 | return mode; | ||
254 | } | ||
255 | |||
256 | static void dib8000_set_acquisition_mode(struct dib8000_state *state) | ||
257 | { | ||
258 | u16 nud = dib8000_read_word(state, 298); | ||
259 | nud |= (1 << 3) | (1 << 0); | ||
260 | dprintk("acquisition mode activated"); | ||
261 | dib8000_write_word(state, 298, nud); | ||
262 | } | ||
263 | |||
264 | static int dib8000_set_output_mode(struct dib8000_state *state, int mode) | ||
265 | { | ||
266 | u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ | ||
267 | |||
268 | outreg = 0; | ||
269 | fifo_threshold = 1792; | ||
270 | smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); | ||
271 | |||
272 | dprintk("-I- Setting output mode for demod %p to %d", &state->fe, mode); | ||
273 | |||
274 | switch (mode) { | ||
275 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
276 | outreg = (1 << 10); /* 0x0400 */ | ||
277 | break; | ||
278 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
279 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
280 | break; | ||
281 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
282 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ | ||
283 | break; | ||
284 | case OUTMODE_DIVERSITY: | ||
285 | if (state->cfg.hostbus_diversity) { | ||
286 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
287 | sram &= 0xfdff; | ||
288 | } else | ||
289 | sram |= 0x0c00; | ||
290 | break; | ||
291 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
292 | smo_mode |= (3 << 1); | ||
293 | fifo_threshold = 512; | ||
294 | outreg = (1 << 10) | (5 << 6); | ||
295 | break; | ||
296 | case OUTMODE_HIGH_Z: // disable | ||
297 | outreg = 0; | ||
298 | break; | ||
299 | |||
300 | case OUTMODE_ANALOG_ADC: | ||
301 | outreg = (1 << 10) | (3 << 6); | ||
302 | dib8000_set_acquisition_mode(state); | ||
303 | break; | ||
304 | |||
305 | default: | ||
306 | dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe); | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
311 | smo_mode |= (1 << 5); | ||
312 | |||
313 | dib8000_write_word(state, 299, smo_mode); | ||
314 | dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */ | ||
315 | dib8000_write_word(state, 1286, outreg); | ||
316 | dib8000_write_word(state, 1291, sram); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) | ||
322 | { | ||
323 | struct dib8000_state *state = fe->demodulator_priv; | ||
324 | u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0; | ||
325 | |||
326 | if (!state->differential_constellation) { | ||
327 | dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 | ||
328 | dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 | ||
329 | } else { | ||
330 | dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0 | ||
331 | dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0 | ||
332 | } | ||
333 | state->diversity_onoff = onoff; | ||
334 | |||
335 | switch (onoff) { | ||
336 | case 0: /* only use the internal way - not the diversity input */ | ||
337 | dib8000_write_word(state, 270, 1); | ||
338 | dib8000_write_word(state, 271, 0); | ||
339 | break; | ||
340 | case 1: /* both ways */ | ||
341 | dib8000_write_word(state, 270, 6); | ||
342 | dib8000_write_word(state, 271, 6); | ||
343 | break; | ||
344 | case 2: /* only the diversity input */ | ||
345 | dib8000_write_word(state, 270, 0); | ||
346 | dib8000_write_word(state, 271, 1); | ||
347 | break; | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode) | ||
353 | { | ||
354 | /* by default everything is going to be powered off */ | ||
355 | u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff, | ||
356 | reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00; | ||
357 | |||
358 | /* now, depending on the requested mode, we power on */ | ||
359 | switch (mode) { | ||
360 | /* power up everything in the demod */ | ||
361 | case DIB8000M_POWER_ALL: | ||
362 | reg_774 = 0x0000; | ||
363 | reg_775 = 0x0000; | ||
364 | reg_776 = 0x0000; | ||
365 | reg_900 &= 0xfffc; | ||
366 | reg_1280 &= 0x00ff; | ||
367 | break; | ||
368 | case DIB8000M_POWER_INTERFACE_ONLY: | ||
369 | reg_1280 &= 0x00ff; | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280); | ||
374 | dib8000_write_word(state, 774, reg_774); | ||
375 | dib8000_write_word(state, 775, reg_775); | ||
376 | dib8000_write_word(state, 776, reg_776); | ||
377 | dib8000_write_word(state, 900, reg_900); | ||
378 | dib8000_write_word(state, 1280, reg_1280); | ||
379 | } | ||
380 | |||
381 | static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) | ||
382 | { | ||
383 | int ret = 0; | ||
384 | u16 reg_907 = dib8000_read_word(state, 907), reg_908 = dib8000_read_word(state, 908); | ||
385 | |||
386 | switch (no) { | ||
387 | case DIBX000_SLOW_ADC_ON: | ||
388 | reg_908 |= (1 << 1) | (1 << 0); | ||
389 | ret |= dib8000_write_word(state, 908, reg_908); | ||
390 | reg_908 &= ~(1 << 1); | ||
391 | break; | ||
392 | |||
393 | case DIBX000_SLOW_ADC_OFF: | ||
394 | reg_908 |= (1 << 1) | (1 << 0); | ||
395 | break; | ||
396 | |||
397 | case DIBX000_ADC_ON: | ||
398 | reg_907 &= 0x0fff; | ||
399 | reg_908 &= 0x0003; | ||
400 | break; | ||
401 | |||
402 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
403 | reg_907 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
404 | reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
405 | break; | ||
406 | |||
407 | case DIBX000_VBG_ENABLE: | ||
408 | reg_907 &= ~(1 << 15); | ||
409 | break; | ||
410 | |||
411 | case DIBX000_VBG_DISABLE: | ||
412 | reg_907 |= (1 << 15); | ||
413 | break; | ||
414 | |||
415 | default: | ||
416 | break; | ||
417 | } | ||
418 | |||
419 | ret |= dib8000_write_word(state, 907, reg_907); | ||
420 | ret |= dib8000_write_word(state, 908, reg_908); | ||
421 | |||
422 | return ret; | ||
423 | } | ||
424 | |||
425 | static int dib8000_set_bandwidth(struct dib8000_state *state, u32 bw) | ||
426 | { | ||
427 | u32 timf; | ||
428 | |||
429 | if (bw == 0) | ||
430 | bw = 6000; | ||
431 | |||
432 | if (state->timf == 0) { | ||
433 | dprintk("using default timf"); | ||
434 | timf = state->timf_default; | ||
435 | } else { | ||
436 | dprintk("using updated timf"); | ||
437 | timf = state->timf; | ||
438 | } | ||
439 | |||
440 | dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff)); | ||
441 | dib8000_write_word(state, 30, (u16) ((timf) & 0xffff)); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int dib8000_sad_calib(struct dib8000_state *state) | ||
447 | { | ||
448 | /* internal */ | ||
449 | dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); | ||
450 | dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096 | ||
451 | |||
452 | /* do the calibration */ | ||
453 | dib8000_write_word(state, 923, (1 << 0)); | ||
454 | dib8000_write_word(state, 923, (0 << 0)); | ||
455 | |||
456 | msleep(1); | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | ||
461 | { | ||
462 | struct dib8000_state *state = fe->demodulator_priv; | ||
463 | if (value > 4095) | ||
464 | value = 4095; | ||
465 | state->wbd_ref = value; | ||
466 | return dib8000_write_word(state, 106, value); | ||
467 | } | ||
468 | |||
469 | EXPORT_SYMBOL(dib8000_set_wbd_ref); | ||
470 | static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) | ||
471 | { | ||
472 | dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); | ||
473 | dib8000_write_word(state, 23, (u16) (((bw->internal * 1000) >> 16) & 0xffff)); /* P_sec_len */ | ||
474 | dib8000_write_word(state, 24, (u16) ((bw->internal * 1000) & 0xffff)); | ||
475 | dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff)); | ||
476 | dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff)); | ||
477 | dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003)); | ||
478 | |||
479 | dib8000_write_word(state, 922, bw->sad_cfg); | ||
480 | } | ||
481 | |||
482 | static void dib8000_reset_pll(struct dib8000_state *state) | ||
483 | { | ||
484 | const struct dibx000_bandwidth_config *pll = state->cfg.pll; | ||
485 | u16 clk_cfg1; | ||
486 | |||
487 | // clk_cfg0 | ||
488 | dib8000_write_word(state, 901, (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); | ||
489 | |||
490 | // clk_cfg1 | ||
491 | clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | | ||
492 | (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) | (pll->pll_range << 1) | (pll->pll_reset << 0); | ||
493 | |||
494 | dib8000_write_word(state, 902, clk_cfg1); | ||
495 | clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); | ||
496 | dib8000_write_word(state, 902, clk_cfg1); | ||
497 | |||
498 | dprintk("clk_cfg1: 0x%04x", clk_cfg1); /* 0x507 1 0 1 000 0 0 11 1 */ | ||
499 | |||
500 | /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ | ||
501 | if (state->cfg.pll->ADClkSrc == 0) | ||
502 | dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1)); | ||
503 | else if (state->cfg.refclksel != 0) | ||
504 | dib8000_write_word(state, 904, | ||
505 | (0 << 15) | (1 << 12) | ((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) | (pll-> | ||
506 | ADClkSrc << 7) | (0 << 1)); | ||
507 | else | ||
508 | dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | (3 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1)); | ||
509 | |||
510 | dib8000_reset_pll_common(state, pll); | ||
511 | } | ||
512 | |||
513 | static int dib8000_reset_gpio(struct dib8000_state *st) | ||
514 | { | ||
515 | /* reset the GPIOs */ | ||
516 | dib8000_write_word(st, 1029, st->cfg.gpio_dir); | ||
517 | dib8000_write_word(st, 1030, st->cfg.gpio_val); | ||
518 | |||
519 | /* TODO 782 is P_gpio_od */ | ||
520 | |||
521 | dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos); | ||
522 | |||
523 | dib8000_write_word(st, 1037, st->cfg.pwm_freq_div); | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val) | ||
528 | { | ||
529 | st->cfg.gpio_dir = dib8000_read_word(st, 1029); | ||
530 | st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */ | ||
531 | st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */ | ||
532 | dib8000_write_word(st, 1029, st->cfg.gpio_dir); | ||
533 | |||
534 | st->cfg.gpio_val = dib8000_read_word(st, 1030); | ||
535 | st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */ | ||
536 | st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */ | ||
537 | dib8000_write_word(st, 1030, st->cfg.gpio_val); | ||
538 | |||
539 | dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | ||
545 | { | ||
546 | struct dib8000_state *state = fe->demodulator_priv; | ||
547 | return dib8000_cfg_gpio(state, num, dir, val); | ||
548 | } | ||
549 | |||
550 | EXPORT_SYMBOL(dib8000_set_gpio); | ||
551 | static const u16 dib8000_defaults[] = { | ||
552 | /* auto search configuration - lock0 by default waiting | ||
553 | * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */ | ||
554 | 3, 7, | ||
555 | 0x0004, | ||
556 | 0x0400, | ||
557 | 0x0814, | ||
558 | |||
559 | 12, 11, | ||
560 | 0x001b, | ||
561 | 0x7740, | ||
562 | 0x005b, | ||
563 | 0x8d80, | ||
564 | 0x01c9, | ||
565 | 0xc380, | ||
566 | 0x0000, | ||
567 | 0x0080, | ||
568 | 0x0000, | ||
569 | 0x0090, | ||
570 | 0x0001, | ||
571 | 0xd4c0, | ||
572 | |||
573 | /*1, 32, | ||
574 | 0x6680 // P_corm_thres Lock algorithms configuration */ | ||
575 | |||
576 | 11, 80, /* set ADC level to -16 */ | ||
577 | (1 << 13) - 825 - 117, | ||
578 | (1 << 13) - 837 - 117, | ||
579 | (1 << 13) - 811 - 117, | ||
580 | (1 << 13) - 766 - 117, | ||
581 | (1 << 13) - 737 - 117, | ||
582 | (1 << 13) - 693 - 117, | ||
583 | (1 << 13) - 648 - 117, | ||
584 | (1 << 13) - 619 - 117, | ||
585 | (1 << 13) - 575 - 117, | ||
586 | (1 << 13) - 531 - 117, | ||
587 | (1 << 13) - 501 - 117, | ||
588 | |||
589 | 4, 108, | ||
590 | 0, | ||
591 | 0, | ||
592 | 0, | ||
593 | 0, | ||
594 | |||
595 | 1, 175, | ||
596 | 0x0410, | ||
597 | 1, 179, | ||
598 | 8192, // P_fft_nb_to_cut | ||
599 | |||
600 | 6, 181, | ||
601 | 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800 | ||
602 | 0x2800, | ||
603 | 0x2800, | ||
604 | 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800 | ||
605 | 0x2800, | ||
606 | 0x2800, | ||
607 | |||
608 | 2, 193, | ||
609 | 0x0666, // P_pha3_thres | ||
610 | 0x0000, // P_cti_use_cpe, P_cti_use_prog | ||
611 | |||
612 | 2, 205, | ||
613 | 0x200f, // P_cspu_regul, P_cspu_win_cut | ||
614 | 0x000f, // P_des_shift_work | ||
615 | |||
616 | 5, 215, | ||
617 | 0x023d, // P_adp_regul_cnt | ||
618 | 0x00a4, // P_adp_noise_cnt | ||
619 | 0x00a4, // P_adp_regul_ext | ||
620 | 0x7ff0, // P_adp_noise_ext | ||
621 | 0x3ccc, // P_adp_fil | ||
622 | |||
623 | 1, 230, | ||
624 | 0x0000, // P_2d_byp_ti_num | ||
625 | |||
626 | 1, 263, | ||
627 | 0x800, //P_equal_thres_wgn | ||
628 | |||
629 | 1, 268, | ||
630 | (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode | ||
631 | |||
632 | 1, 270, | ||
633 | 0x0001, // P_div_lock0_wait | ||
634 | 1, 285, | ||
635 | 0x0020, //p_fec_ | ||
636 | 1, 299, | ||
637 | 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
638 | |||
639 | 1, 338, | ||
640 | (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1 | ||
641 | (1 << 10) | // P_ctrl_pre_freq_mode_sat=1 | ||
642 | (0 << 9) | // P_ctrl_pre_freq_inh=0 | ||
643 | (3 << 5) | // P_ctrl_pre_freq_step=3 | ||
644 | (1 << 0), // P_pre_freq_win_len=1 | ||
645 | |||
646 | 1, 903, | ||
647 | (0 << 4) | 2, // P_divclksel=0 P_divbitsel=2 (was clk=3,bit=1 for MPW) | ||
648 | |||
649 | 0, | ||
650 | }; | ||
651 | |||
652 | static u16 dib8000_identify(struct i2c_device *client) | ||
653 | { | ||
654 | u16 value; | ||
655 | |||
656 | //because of glitches sometimes | ||
657 | value = dib8000_i2c_read16(client, 896); | ||
658 | |||
659 | if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) { | ||
660 | dprintk("wrong Vendor ID (read=0x%x)", value); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | value = dib8000_i2c_read16(client, 897); | ||
665 | if (value != 0x8000 && value != 0x8001 && value != 0x8002) { | ||
666 | dprintk("wrong Device ID (%x)", value); | ||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | switch (value) { | ||
671 | case 0x8000: | ||
672 | dprintk("found DiB8000A"); | ||
673 | break; | ||
674 | case 0x8001: | ||
675 | dprintk("found DiB8000B"); | ||
676 | break; | ||
677 | case 0x8002: | ||
678 | dprintk("found DiB8000C"); | ||
679 | break; | ||
680 | } | ||
681 | return value; | ||
682 | } | ||
683 | |||
684 | static int dib8000_reset(struct dvb_frontend *fe) | ||
685 | { | ||
686 | struct dib8000_state *state = fe->demodulator_priv; | ||
687 | |||
688 | dib8000_write_word(state, 1287, 0x0003); /* sram lead in, rdy */ | ||
689 | |||
690 | if ((state->revision = dib8000_identify(&state->i2c)) == 0) | ||
691 | return -EINVAL; | ||
692 | |||
693 | if (state->revision == 0x8000) | ||
694 | dprintk("error : dib8000 MA not supported"); | ||
695 | |||
696 | dibx000_reset_i2c_master(&state->i2c_master); | ||
697 | |||
698 | dib8000_set_power_mode(state, DIB8000M_POWER_ALL); | ||
699 | |||
700 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ | ||
701 | dib8000_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
702 | |||
703 | /* restart all parts */ | ||
704 | dib8000_write_word(state, 770, 0xffff); | ||
705 | dib8000_write_word(state, 771, 0xffff); | ||
706 | dib8000_write_word(state, 772, 0xfffc); | ||
707 | dib8000_write_word(state, 898, 0x000c); // sad | ||
708 | dib8000_write_word(state, 1280, 0x004d); | ||
709 | dib8000_write_word(state, 1281, 0x000c); | ||
710 | |||
711 | dib8000_write_word(state, 770, 0x0000); | ||
712 | dib8000_write_word(state, 771, 0x0000); | ||
713 | dib8000_write_word(state, 772, 0x0000); | ||
714 | dib8000_write_word(state, 898, 0x0004); // sad | ||
715 | dib8000_write_word(state, 1280, 0x0000); | ||
716 | dib8000_write_word(state, 1281, 0x0000); | ||
717 | |||
718 | /* drives */ | ||
719 | if (state->cfg.drives) | ||
720 | dib8000_write_word(state, 906, state->cfg.drives); | ||
721 | else { | ||
722 | dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal."); | ||
723 | dib8000_write_word(state, 906, 0x2d98); // min drive SDRAM - not optimal - adjust | ||
724 | } | ||
725 | |||
726 | dib8000_reset_pll(state); | ||
727 | |||
728 | if (dib8000_reset_gpio(state) != 0) | ||
729 | dprintk("GPIO reset was not successful."); | ||
730 | |||
731 | if (dib8000_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | ||
732 | dprintk("OUTPUT_MODE could not be resetted."); | ||
733 | |||
734 | state->current_agc = NULL; | ||
735 | |||
736 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
737 | /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */ | ||
738 | if (state->cfg.pll->ifreq == 0) | ||
739 | dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */ | ||
740 | else | ||
741 | dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */ | ||
742 | |||
743 | { | ||
744 | u16 l = 0, r; | ||
745 | const u16 *n; | ||
746 | n = dib8000_defaults; | ||
747 | l = *n++; | ||
748 | while (l) { | ||
749 | r = *n++; | ||
750 | do { | ||
751 | dib8000_write_word(state, r, *n++); | ||
752 | r++; | ||
753 | } while (--l); | ||
754 | l = *n++; | ||
755 | } | ||
756 | } | ||
757 | state->isdbt_cfg_loaded = 0; | ||
758 | |||
759 | //div_cfg override for special configs | ||
760 | if (state->cfg.div_cfg != 0) | ||
761 | dib8000_write_word(state, 903, state->cfg.div_cfg); | ||
762 | |||
763 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
764 | dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1)); | ||
765 | |||
766 | dib8000_set_bandwidth(state, 6000); | ||
767 | |||
768 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
769 | dib8000_sad_calib(state); | ||
770 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
771 | |||
772 | dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY); | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static void dib8000_restart_agc(struct dib8000_state *state) | ||
778 | { | ||
779 | // P_restart_iqc & P_restart_agc | ||
780 | dib8000_write_word(state, 770, 0x0a00); | ||
781 | dib8000_write_word(state, 770, 0x0000); | ||
782 | } | ||
783 | |||
784 | static int dib8000_update_lna(struct dib8000_state *state) | ||
785 | { | ||
786 | u16 dyn_gain; | ||
787 | |||
788 | if (state->cfg.update_lna) { | ||
789 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
790 | dyn_gain = dib8000_read_word(state, 390); | ||
791 | |||
792 | if (state->cfg.update_lna(&state->fe, dyn_gain)) { // LNA has changed | ||
793 | dib8000_restart_agc(state); | ||
794 | return 1; | ||
795 | } | ||
796 | } | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) | ||
801 | { | ||
802 | struct dibx000_agc_config *agc = NULL; | ||
803 | int i; | ||
804 | if (state->current_band == band && state->current_agc != NULL) | ||
805 | return 0; | ||
806 | state->current_band = band; | ||
807 | |||
808 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
809 | if (state->cfg.agc[i].band_caps & band) { | ||
810 | agc = &state->cfg.agc[i]; | ||
811 | break; | ||
812 | } | ||
813 | |||
814 | if (agc == NULL) { | ||
815 | dprintk("no valid AGC configuration found for band 0x%02x", band); | ||
816 | return -EINVAL; | ||
817 | } | ||
818 | |||
819 | state->current_agc = agc; | ||
820 | |||
821 | /* AGC */ | ||
822 | dib8000_write_word(state, 76, agc->setup); | ||
823 | dib8000_write_word(state, 77, agc->inv_gain); | ||
824 | dib8000_write_word(state, 78, agc->time_stabiliz); | ||
825 | dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock); | ||
826 | |||
827 | // Demod AGC loop configuration | ||
828 | dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
829 | dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp); | ||
830 | |||
831 | dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d", | ||
832 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
833 | |||
834 | /* AGC continued */ | ||
835 | if (state->wbd_ref != 0) | ||
836 | dib8000_write_word(state, 106, state->wbd_ref); | ||
837 | else // use default | ||
838 | dib8000_write_word(state, 106, agc->wbd_ref); | ||
839 | dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); | ||
840 | dib8000_write_word(state, 108, agc->agc1_max); | ||
841 | dib8000_write_word(state, 109, agc->agc1_min); | ||
842 | dib8000_write_word(state, 110, agc->agc2_max); | ||
843 | dib8000_write_word(state, 111, agc->agc2_min); | ||
844 | dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2); | ||
845 | dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
846 | dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
847 | dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
848 | |||
849 | dib8000_write_word(state, 75, agc->agc1_pt3); | ||
850 | dib8000_write_word(state, 923, (dib8000_read_word(state, 923) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); /*LB : 929 -> 923 */ | ||
851 | |||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | static int dib8000_agc_soft_split(struct dib8000_state *state) | ||
856 | { | ||
857 | u16 agc, split_offset; | ||
858 | |||
859 | if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) | ||
860 | return FE_CALLBACK_TIME_NEVER; | ||
861 | |||
862 | // n_agc_global | ||
863 | agc = dib8000_read_word(state, 390); | ||
864 | |||
865 | if (agc > state->current_agc->split.min_thres) | ||
866 | split_offset = state->current_agc->split.min; | ||
867 | else if (agc < state->current_agc->split.max_thres) | ||
868 | split_offset = state->current_agc->split.max; | ||
869 | else | ||
870 | split_offset = state->current_agc->split.max * | ||
871 | (agc - state->current_agc->split.min_thres) / (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | ||
872 | |||
873 | dprintk("AGC split_offset: %d", split_offset); | ||
874 | |||
875 | // P_agc_force_split and P_agc_split_offset | ||
876 | dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset); | ||
877 | return 5000; | ||
878 | } | ||
879 | |||
880 | static int dib8000_agc_startup(struct dvb_frontend *fe) | ||
881 | { | ||
882 | struct dib8000_state *state = fe->demodulator_priv; | ||
883 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
884 | |||
885 | int ret = 0; | ||
886 | |||
887 | switch (*tune_state) { | ||
888 | case CT_AGC_START: | ||
889 | // set power-up level: interf+analog+AGC | ||
890 | |||
891 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
892 | |||
893 | if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) { | ||
894 | *tune_state = CT_AGC_STOP; | ||
895 | state->status = FE_STATUS_TUNE_FAILED; | ||
896 | break; | ||
897 | } | ||
898 | |||
899 | ret = 70; | ||
900 | *tune_state = CT_AGC_STEP_0; | ||
901 | break; | ||
902 | |||
903 | case CT_AGC_STEP_0: | ||
904 | //AGC initialization | ||
905 | if (state->cfg.agc_control) | ||
906 | state->cfg.agc_control(&state->fe, 1); | ||
907 | |||
908 | dib8000_restart_agc(state); | ||
909 | |||
910 | // wait AGC rough lock time | ||
911 | ret = 50; | ||
912 | *tune_state = CT_AGC_STEP_1; | ||
913 | break; | ||
914 | |||
915 | case CT_AGC_STEP_1: | ||
916 | // wait AGC accurate lock time | ||
917 | ret = 70; | ||
918 | |||
919 | if (dib8000_update_lna(state)) | ||
920 | // wait only AGC rough lock time | ||
921 | ret = 50; | ||
922 | else | ||
923 | *tune_state = CT_AGC_STEP_2; | ||
924 | break; | ||
925 | |||
926 | case CT_AGC_STEP_2: | ||
927 | dib8000_agc_soft_split(state); | ||
928 | |||
929 | if (state->cfg.agc_control) | ||
930 | state->cfg.agc_control(&state->fe, 0); | ||
931 | |||
932 | *tune_state = CT_AGC_STOP; | ||
933 | break; | ||
934 | default: | ||
935 | ret = dib8000_agc_soft_split(state); | ||
936 | break; | ||
937 | } | ||
938 | return ret; | ||
939 | |||
940 | } | ||
941 | |||
942 | static void dib8000_update_timf(struct dib8000_state *state) | ||
943 | { | ||
944 | u32 timf = state->timf = dib8000_read32(state, 435); | ||
945 | |||
946 | dib8000_write_word(state, 29, (u16) (timf >> 16)); | ||
947 | dib8000_write_word(state, 30, (u16) (timf & 0xffff)); | ||
948 | dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); | ||
949 | } | ||
950 | |||
951 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) | ||
952 | { | ||
953 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; | ||
954 | u8 guard, crate, constellation, timeI; | ||
955 | u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | ||
956 | u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled | ||
957 | const s16 *ncoeff, *ana_fe; | ||
958 | u16 tmcc_pow = 0; | ||
959 | u16 coff_pow = 0x2800; | ||
960 | u16 init_prbs = 0xfff; | ||
961 | u16 ana_gain = 0; | ||
962 | u16 adc_target_16dB[11] = { | ||
963 | (1 << 13) - 825 - 117, | ||
964 | (1 << 13) - 837 - 117, | ||
965 | (1 << 13) - 811 - 117, | ||
966 | (1 << 13) - 766 - 117, | ||
967 | (1 << 13) - 737 - 117, | ||
968 | (1 << 13) - 693 - 117, | ||
969 | (1 << 13) - 648 - 117, | ||
970 | (1 << 13) - 619 - 117, | ||
971 | (1 << 13) - 575 - 117, | ||
972 | (1 << 13) - 531 - 117, | ||
973 | (1 << 13) - 501 - 117 | ||
974 | }; | ||
975 | |||
976 | if (state->ber_monitored_layer != LAYER_ALL) | ||
977 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); | ||
978 | else | ||
979 | dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); | ||
980 | |||
981 | i = dib8000_read_word(state, 26) & 1; // P_dds_invspec | ||
982 | dib8000_write_word(state, 26, state->fe.dtv_property_cache.inversion ^ i); | ||
983 | |||
984 | if (state->fe.dtv_property_cache.isdbt_sb_mode) { | ||
985 | //compute new dds_freq for the seg and adjust prbs | ||
986 | int seg_offset = | ||
987 | state->fe.dtv_property_cache.isdbt_sb_segment_idx - (state->fe.dtv_property_cache.isdbt_sb_segment_count / 2) - | ||
988 | (state->fe.dtv_property_cache.isdbt_sb_segment_count % 2); | ||
989 | int clk = state->cfg.pll->internal; | ||
990 | u32 segtodds = ((u32) (430 << 23) / clk) << 3; // segtodds = SegBW / Fclk * pow(2,26) | ||
991 | int dds_offset = seg_offset * segtodds; | ||
992 | int new_dds, sub_channel; | ||
993 | if ((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) == 0) // if even | ||
994 | dds_offset -= (int)(segtodds / 2); | ||
995 | |||
996 | if (state->cfg.pll->ifreq == 0) { | ||
997 | if ((state->fe.dtv_property_cache.inversion ^ i) == 0) { | ||
998 | dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); | ||
999 | new_dds = dds_offset; | ||
1000 | } else | ||
1001 | new_dds = dds_offset; | ||
1002 | |||
1003 | // We shift tuning frequency if the wanted segment is : | ||
1004 | // - the segment of center frequency with an odd total number of segments | ||
1005 | // - the segment to the left of center frequency with an even total number of segments | ||
1006 | // - the segment to the right of center frequency with an even total number of segments | ||
1007 | if ((state->fe.dtv_property_cache.delivery_system == SYS_ISDBT) && (state->fe.dtv_property_cache.isdbt_sb_mode == 1) | ||
1008 | && | ||
1009 | (((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) | ||
1010 | && (state->fe.dtv_property_cache.isdbt_sb_segment_idx == | ||
1011 | ((state->fe.dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
1012 | || (((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1013 | && (state->fe.dtv_property_cache.isdbt_sb_segment_idx == (state->fe.dtv_property_cache.isdbt_sb_segment_count / 2))) | ||
1014 | || (((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1015 | && (state->fe.dtv_property_cache.isdbt_sb_segment_idx == | ||
1016 | ((state->fe.dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
1017 | )) { | ||
1018 | new_dds -= ((u32) (850 << 22) / clk) << 4; // new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26) | ||
1019 | } | ||
1020 | } else { | ||
1021 | if ((state->fe.dtv_property_cache.inversion ^ i) == 0) | ||
1022 | new_dds = state->cfg.pll->ifreq - dds_offset; | ||
1023 | else | ||
1024 | new_dds = state->cfg.pll->ifreq + dds_offset; | ||
1025 | } | ||
1026 | dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff)); | ||
1027 | dib8000_write_word(state, 28, (u16) (new_dds & 0xffff)); | ||
1028 | if (state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) // if odd | ||
1029 | sub_channel = ((state->fe.dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3; | ||
1030 | else // if even | ||
1031 | sub_channel = ((state->fe.dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3; | ||
1032 | sub_channel -= 6; | ||
1033 | |||
1034 | if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K | ||
1035 | || state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) { | ||
1036 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); //adp_pass =1 | ||
1037 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); //pha3_force_pha_shift = 1 | ||
1038 | } else { | ||
1039 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); //adp_pass =0 | ||
1040 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); //pha3_force_pha_shift = 0 | ||
1041 | } | ||
1042 | |||
1043 | switch (state->fe.dtv_property_cache.transmission_mode) { | ||
1044 | case TRANSMISSION_MODE_2K: | ||
1045 | switch (sub_channel) { | ||
1046 | case -6: | ||
1047 | init_prbs = 0x0; | ||
1048 | break; // 41, 0, 1 | ||
1049 | case -5: | ||
1050 | init_prbs = 0x423; | ||
1051 | break; // 02~04 | ||
1052 | case -4: | ||
1053 | init_prbs = 0x9; | ||
1054 | break; // 05~07 | ||
1055 | case -3: | ||
1056 | init_prbs = 0x5C7; | ||
1057 | break; // 08~10 | ||
1058 | case -2: | ||
1059 | init_prbs = 0x7A6; | ||
1060 | break; // 11~13 | ||
1061 | case -1: | ||
1062 | init_prbs = 0x3D8; | ||
1063 | break; // 14~16 | ||
1064 | case 0: | ||
1065 | init_prbs = 0x527; | ||
1066 | break; // 17~19 | ||
1067 | case 1: | ||
1068 | init_prbs = 0x7FF; | ||
1069 | break; // 20~22 | ||
1070 | case 2: | ||
1071 | init_prbs = 0x79B; | ||
1072 | break; // 23~25 | ||
1073 | case 3: | ||
1074 | init_prbs = 0x3D6; | ||
1075 | break; // 26~28 | ||
1076 | case 4: | ||
1077 | init_prbs = 0x3A2; | ||
1078 | break; // 29~31 | ||
1079 | case 5: | ||
1080 | init_prbs = 0x53B; | ||
1081 | break; // 32~34 | ||
1082 | case 6: | ||
1083 | init_prbs = 0x2F4; | ||
1084 | break; // 35~37 | ||
1085 | default: | ||
1086 | case 7: | ||
1087 | init_prbs = 0x213; | ||
1088 | break; // 38~40 | ||
1089 | } | ||
1090 | break; | ||
1091 | |||
1092 | case TRANSMISSION_MODE_4K: | ||
1093 | switch (sub_channel) { | ||
1094 | case -6: | ||
1095 | init_prbs = 0x0; | ||
1096 | break; // 41, 0, 1 | ||
1097 | case -5: | ||
1098 | init_prbs = 0x208; | ||
1099 | break; // 02~04 | ||
1100 | case -4: | ||
1101 | init_prbs = 0xC3; | ||
1102 | break; // 05~07 | ||
1103 | case -3: | ||
1104 | init_prbs = 0x7B9; | ||
1105 | break; // 08~10 | ||
1106 | case -2: | ||
1107 | init_prbs = 0x423; | ||
1108 | break; // 11~13 | ||
1109 | case -1: | ||
1110 | init_prbs = 0x5C7; | ||
1111 | break; // 14~16 | ||
1112 | case 0: | ||
1113 | init_prbs = 0x3D8; | ||
1114 | break; // 17~19 | ||
1115 | case 1: | ||
1116 | init_prbs = 0x7FF; | ||
1117 | break; // 20~22 | ||
1118 | case 2: | ||
1119 | init_prbs = 0x3D6; | ||
1120 | break; // 23~25 | ||
1121 | case 3: | ||
1122 | init_prbs = 0x53B; | ||
1123 | break; // 26~28 | ||
1124 | case 4: | ||
1125 | init_prbs = 0x213; | ||
1126 | break; // 29~31 | ||
1127 | case 5: | ||
1128 | init_prbs = 0x29; | ||
1129 | break; // 32~34 | ||
1130 | case 6: | ||
1131 | init_prbs = 0xD0; | ||
1132 | break; // 35~37 | ||
1133 | default: | ||
1134 | case 7: | ||
1135 | init_prbs = 0x48E; | ||
1136 | break; // 38~40 | ||
1137 | } | ||
1138 | break; | ||
1139 | |||
1140 | default: | ||
1141 | case TRANSMISSION_MODE_8K: | ||
1142 | switch (sub_channel) { | ||
1143 | case -6: | ||
1144 | init_prbs = 0x0; | ||
1145 | break; // 41, 0, 1 | ||
1146 | case -5: | ||
1147 | init_prbs = 0x740; | ||
1148 | break; // 02~04 | ||
1149 | case -4: | ||
1150 | init_prbs = 0x069; | ||
1151 | break; // 05~07 | ||
1152 | case -3: | ||
1153 | init_prbs = 0x7DD; | ||
1154 | break; // 08~10 | ||
1155 | case -2: | ||
1156 | init_prbs = 0x208; | ||
1157 | break; // 11~13 | ||
1158 | case -1: | ||
1159 | init_prbs = 0x7B9; | ||
1160 | break; // 14~16 | ||
1161 | case 0: | ||
1162 | init_prbs = 0x5C7; | ||
1163 | break; // 17~19 | ||
1164 | case 1: | ||
1165 | init_prbs = 0x7FF; | ||
1166 | break; // 20~22 | ||
1167 | case 2: | ||
1168 | init_prbs = 0x53B; | ||
1169 | break; // 23~25 | ||
1170 | case 3: | ||
1171 | init_prbs = 0x29; | ||
1172 | break; // 26~28 | ||
1173 | case 4: | ||
1174 | init_prbs = 0x48E; | ||
1175 | break; // 29~31 | ||
1176 | case 5: | ||
1177 | init_prbs = 0x4C4; | ||
1178 | break; // 32~34 | ||
1179 | case 6: | ||
1180 | init_prbs = 0x367; | ||
1181 | break; // 33~37 | ||
1182 | default: | ||
1183 | case 7: | ||
1184 | init_prbs = 0x684; | ||
1185 | break; // 38~40 | ||
1186 | } | ||
1187 | break; | ||
1188 | } | ||
1189 | } else { // if not state->fe.dtv_property_cache.isdbt_sb_mode | ||
1190 | dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff)); | ||
1191 | dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff)); | ||
1192 | dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003)); | ||
1193 | } | ||
1194 | /*P_mode == ?? */ | ||
1195 | dib8000_write_word(state, 10, (seq << 4)); | ||
1196 | // dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000); | ||
1197 | |||
1198 | switch (state->fe.dtv_property_cache.guard_interval) { | ||
1199 | case GUARD_INTERVAL_1_32: | ||
1200 | guard = 0; | ||
1201 | break; | ||
1202 | case GUARD_INTERVAL_1_16: | ||
1203 | guard = 1; | ||
1204 | break; | ||
1205 | case GUARD_INTERVAL_1_8: | ||
1206 | guard = 2; | ||
1207 | break; | ||
1208 | case GUARD_INTERVAL_1_4: | ||
1209 | default: | ||
1210 | guard = 3; | ||
1211 | break; | ||
1212 | } | ||
1213 | |||
1214 | dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3)); // ADDR 1 | ||
1215 | |||
1216 | max_constellation = DQPSK; | ||
1217 | for (i = 0; i < 3; i++) { | ||
1218 | switch (state->fe.dtv_property_cache.layer[i].modulation) { | ||
1219 | case DQPSK: | ||
1220 | constellation = 0; | ||
1221 | break; | ||
1222 | case QPSK: | ||
1223 | constellation = 1; | ||
1224 | break; | ||
1225 | case QAM_16: | ||
1226 | constellation = 2; | ||
1227 | break; | ||
1228 | case QAM_64: | ||
1229 | default: | ||
1230 | constellation = 3; | ||
1231 | break; | ||
1232 | } | ||
1233 | |||
1234 | switch (state->fe.dtv_property_cache.layer[i].fec) { | ||
1235 | case FEC_1_2: | ||
1236 | crate = 1; | ||
1237 | break; | ||
1238 | case FEC_2_3: | ||
1239 | crate = 2; | ||
1240 | break; | ||
1241 | case FEC_3_4: | ||
1242 | crate = 3; | ||
1243 | break; | ||
1244 | case FEC_5_6: | ||
1245 | crate = 5; | ||
1246 | break; | ||
1247 | case FEC_7_8: | ||
1248 | default: | ||
1249 | crate = 7; | ||
1250 | break; | ||
1251 | } | ||
1252 | |||
1253 | if ((state->fe.dtv_property_cache.layer[i].interleaving > 0) && | ||
1254 | ((state->fe.dtv_property_cache.layer[i].interleaving <= 3) || | ||
1255 | (state->fe.dtv_property_cache.layer[i].interleaving == 4 && state->fe.dtv_property_cache.isdbt_sb_mode == 1)) | ||
1256 | ) | ||
1257 | timeI = state->fe.dtv_property_cache.layer[i].interleaving; | ||
1258 | else | ||
1259 | timeI = 0; | ||
1260 | dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe.dtv_property_cache.layer[i].segment_count & 0xf) << 6) | | ||
1261 | (crate << 3) | timeI); | ||
1262 | if (state->fe.dtv_property_cache.layer[i].segment_count > 0) { | ||
1263 | switch (max_constellation) { | ||
1264 | case DQPSK: | ||
1265 | case QPSK: | ||
1266 | if (state->fe.dtv_property_cache.layer[i].modulation == QAM_16 || | ||
1267 | state->fe.dtv_property_cache.layer[i].modulation == QAM_64) | ||
1268 | max_constellation = state->fe.dtv_property_cache.layer[i].modulation; | ||
1269 | break; | ||
1270 | case QAM_16: | ||
1271 | if (state->fe.dtv_property_cache.layer[i].modulation == QAM_64) | ||
1272 | max_constellation = state->fe.dtv_property_cache.layer[i].modulation; | ||
1273 | break; | ||
1274 | } | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | mode = fft_to_mode(state); | ||
1279 | |||
1280 | //dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/ | ||
1281 | |||
1282 | dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | | ||
1283 | ((state->fe.dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe.dtv_property_cache. | ||
1284 | isdbt_sb_mode & 1) << 4)); | ||
1285 | |||
1286 | dprintk("mode = %d ; guard = %d", mode, state->fe.dtv_property_cache.guard_interval); | ||
1287 | |||
1288 | /* signal optimization parameter */ | ||
1289 | |||
1290 | if (state->fe.dtv_property_cache.isdbt_partial_reception) { | ||
1291 | seg_diff_mask = (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0]; | ||
1292 | for (i = 1; i < 3; i++) | ||
1293 | nbseg_diff += | ||
1294 | (state->fe.dtv_property_cache.layer[i].modulation == DQPSK) * state->fe.dtv_property_cache.layer[i].segment_count; | ||
1295 | for (i = 0; i < nbseg_diff; i++) | ||
1296 | seg_diff_mask |= 1 << permu_seg[i + 1]; | ||
1297 | } else { | ||
1298 | for (i = 0; i < 3; i++) | ||
1299 | nbseg_diff += | ||
1300 | (state->fe.dtv_property_cache.layer[i].modulation == DQPSK) * state->fe.dtv_property_cache.layer[i].segment_count; | ||
1301 | for (i = 0; i < nbseg_diff; i++) | ||
1302 | seg_diff_mask |= 1 << permu_seg[i]; | ||
1303 | } | ||
1304 | dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask); | ||
1305 | |||
1306 | state->differential_constellation = (seg_diff_mask != 0); | ||
1307 | dib8000_set_diversity_in(&state->fe, state->diversity_onoff); | ||
1308 | |||
1309 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { // ISDB-Tsb | ||
1310 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 1) // 3-segments | ||
1311 | seg_mask13 = 0x00E0; | ||
1312 | else // 1-segment | ||
1313 | seg_mask13 = 0x0040; | ||
1314 | } else | ||
1315 | seg_mask13 = 0x1fff; | ||
1316 | |||
1317 | // WRITE: Mode & Diff mask | ||
1318 | dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask); | ||
1319 | |||
1320 | if ((seg_diff_mask) || (state->fe.dtv_property_cache.isdbt_sb_mode)) | ||
1321 | dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); | ||
1322 | else | ||
1323 | dib8000_write_word(state, 268, (2 << 9) | 39); //init value | ||
1324 | |||
1325 | // ---- SMALL ---- | ||
1326 | // P_small_seg_diff | ||
1327 | dib8000_write_word(state, 352, seg_diff_mask); // ADDR 352 | ||
1328 | |||
1329 | dib8000_write_word(state, 353, seg_mask13); // ADDR 353 | ||
1330 | |||
1331 | /* // P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */ | ||
1332 | // dib8000_write_word(state, 351, (state->fe.dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5 ); | ||
1333 | |||
1334 | // ---- SMALL ---- | ||
1335 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { | ||
1336 | switch (state->fe.dtv_property_cache.transmission_mode) { | ||
1337 | case TRANSMISSION_MODE_2K: | ||
1338 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) { // 1-seg | ||
1339 | if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) // DQPSK | ||
1340 | ncoeff = coeff_2k_sb_1seg_dqpsk; | ||
1341 | else // QPSK or QAM | ||
1342 | ncoeff = coeff_2k_sb_1seg; | ||
1343 | } else { // 3-segments | ||
1344 | if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) { // DQPSK on central segment | ||
1345 | if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) // DQPSK on external segments | ||
1346 | ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; | ||
1347 | else // QPSK or QAM on external segments | ||
1348 | ncoeff = coeff_2k_sb_3seg_0dqpsk; | ||
1349 | } else { // QPSK or QAM on central segment | ||
1350 | if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) // DQPSK on external segments | ||
1351 | ncoeff = coeff_2k_sb_3seg_1dqpsk; | ||
1352 | else // QPSK or QAM on external segments | ||
1353 | ncoeff = coeff_2k_sb_3seg; | ||
1354 | } | ||
1355 | } | ||
1356 | break; | ||
1357 | |||
1358 | case TRANSMISSION_MODE_4K: | ||
1359 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) { // 1-seg | ||
1360 | if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) // DQPSK | ||
1361 | ncoeff = coeff_4k_sb_1seg_dqpsk; | ||
1362 | else // QPSK or QAM | ||
1363 | ncoeff = coeff_4k_sb_1seg; | ||
1364 | } else { // 3-segments | ||
1365 | if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) { // DQPSK on central segment | ||
1366 | if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) { // DQPSK on external segments | ||
1367 | ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; | ||
1368 | } else { // QPSK or QAM on external segments | ||
1369 | ncoeff = coeff_4k_sb_3seg_0dqpsk; | ||
1370 | } | ||
1371 | } else { // QPSK or QAM on central segment | ||
1372 | if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) { // DQPSK on external segments | ||
1373 | ncoeff = coeff_4k_sb_3seg_1dqpsk; | ||
1374 | } else // QPSK or QAM on external segments | ||
1375 | ncoeff = coeff_4k_sb_3seg; | ||
1376 | } | ||
1377 | } | ||
1378 | break; | ||
1379 | |||
1380 | case TRANSMISSION_MODE_AUTO: | ||
1381 | case TRANSMISSION_MODE_8K: | ||
1382 | default: | ||
1383 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) { // 1-seg | ||
1384 | if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) // DQPSK | ||
1385 | ncoeff = coeff_8k_sb_1seg_dqpsk; | ||
1386 | else // QPSK or QAM | ||
1387 | ncoeff = coeff_8k_sb_1seg; | ||
1388 | } else { // 3-segments | ||
1389 | if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) { // DQPSK on central segment | ||
1390 | if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) { // DQPSK on external segments | ||
1391 | ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; | ||
1392 | } else { // QPSK or QAM on external segments | ||
1393 | ncoeff = coeff_8k_sb_3seg_0dqpsk; | ||
1394 | } | ||
1395 | } else { // QPSK or QAM on central segment | ||
1396 | if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) { // DQPSK on external segments | ||
1397 | ncoeff = coeff_8k_sb_3seg_1dqpsk; | ||
1398 | } else // QPSK or QAM on external segments | ||
1399 | ncoeff = coeff_8k_sb_3seg; | ||
1400 | } | ||
1401 | } | ||
1402 | break; | ||
1403 | } | ||
1404 | } | ||
1405 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) | ||
1406 | for (i = 0; i < 8; i++) | ||
1407 | dib8000_write_word(state, 343 + i, ncoeff[i]); | ||
1408 | |||
1409 | // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 | ||
1410 | dib8000_write_word(state, 351, | ||
1411 | (state->fe.dtv_property_cache.isdbt_sb_mode << 9) | (state->fe.dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5); | ||
1412 | |||
1413 | // ---- COFF ---- | ||
1414 | // Carloff, the most robust | ||
1415 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { // Sound Broadcasting mode - use both TMCC and AC pilots | ||
1416 | |||
1417 | // P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64 | ||
1418 | // P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 | ||
1419 | dib8000_write_word(state, 187, | ||
1420 | (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe.dtv_property_cache.isdbt_partial_reception & 1) << 2) | ||
1421 | | 0x3); | ||
1422 | |||
1423 | /* // P_small_coef_ext_enable = 1 */ | ||
1424 | /* dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */ | ||
1425 | |||
1426 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) { // Sound Broadcasting mode 1 seg | ||
1427 | |||
1428 | // P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1) | ||
1429 | if (mode == 3) | ||
1430 | dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14)); | ||
1431 | else | ||
1432 | dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14)); | ||
1433 | // P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, | ||
1434 | // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 | ||
1435 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); | ||
1436 | // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 | ||
1437 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); | ||
1438 | // P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 | ||
1439 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
1440 | |||
1441 | // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k | ||
1442 | dib8000_write_word(state, 181, 300); | ||
1443 | dib8000_write_word(state, 182, 150); | ||
1444 | dib8000_write_word(state, 183, 80); | ||
1445 | dib8000_write_word(state, 184, 300); | ||
1446 | dib8000_write_word(state, 185, 150); | ||
1447 | dib8000_write_word(state, 186, 80); | ||
1448 | } else { // Sound Broadcasting mode 3 seg | ||
1449 | // P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15 | ||
1450 | /* if (mode == 3) */ | ||
1451 | /* dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */ | ||
1452 | /* else */ | ||
1453 | /* dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */ | ||
1454 | dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); | ||
1455 | |||
1456 | // P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, | ||
1457 | // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 | ||
1458 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); | ||
1459 | // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 | ||
1460 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); | ||
1461 | //P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 | ||
1462 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
1463 | |||
1464 | // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k | ||
1465 | dib8000_write_word(state, 181, 350); | ||
1466 | dib8000_write_word(state, 182, 300); | ||
1467 | dib8000_write_word(state, 183, 250); | ||
1468 | dib8000_write_word(state, 184, 350); | ||
1469 | dib8000_write_word(state, 185, 300); | ||
1470 | dib8000_write_word(state, 186, 250); | ||
1471 | } | ||
1472 | |||
1473 | } else if (state->isdbt_cfg_loaded == 0) { // if not Sound Broadcasting mode : put default values for 13 segments | ||
1474 | dib8000_write_word(state, 180, (16 << 6) | 9); | ||
1475 | dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); | ||
1476 | coff_pow = 0x2800; | ||
1477 | for (i = 0; i < 6; i++) | ||
1478 | dib8000_write_word(state, 181 + i, coff_pow); | ||
1479 | |||
1480 | // P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1, | ||
1481 | // P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 | ||
1482 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); | ||
1483 | |||
1484 | // P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 | ||
1485 | dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); | ||
1486 | // P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 | ||
1487 | dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
1488 | } | ||
1489 | // ---- FFT ---- | ||
1490 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1 && state->fe.dtv_property_cache.isdbt_partial_reception == 0) // 1-seg | ||
1491 | dib8000_write_word(state, 178, 64); // P_fft_powrange=64 | ||
1492 | else | ||
1493 | dib8000_write_word(state, 178, 32); // P_fft_powrange=32 | ||
1494 | |||
1495 | /* make the cpil_coff_lock more robust but slower p_coff_winlen | ||
1496 | * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) | ||
1497 | */ | ||
1498 | /* if ( ( nbseg_diff>0)&&(nbseg_diff<13)) | ||
1499 | dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */ | ||
1500 | |||
1501 | dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask); /* P_lmod4_seg_inh */ | ||
1502 | dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask); /* P_pha3_seg_inh */ | ||
1503 | dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask); /* P_tac_seg_inh */ | ||
1504 | if ((!state->fe.dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0)) | ||
1505 | dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ | ||
1506 | else | ||
1507 | dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask); /* P_equal_noise_seg_inh */ | ||
1508 | dib8000_write_word(state, 287, ~seg_mask13 | 0x1000); /* P_tmcc_seg_inh */ | ||
1509 | //dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */ | ||
1510 | if (!autosearching) | ||
1511 | dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ | ||
1512 | else | ||
1513 | dib8000_write_word(state, 288, 0x1fff); //disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. | ||
1514 | dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000); | ||
1515 | |||
1516 | dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask)); /* P_des_seg_enabled */ | ||
1517 | |||
1518 | /* offset loop parameters */ | ||
1519 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { | ||
1520 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) // Sound Broadcasting mode 1 seg | ||
1521 | /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ | ||
1522 | dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40); | ||
1523 | |||
1524 | else // Sound Broadcasting mode 3 seg | ||
1525 | /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ | ||
1526 | dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60); | ||
1527 | } else | ||
1528 | // TODO in 13 seg, timf_alpha can always be the same or not ? | ||
1529 | /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
1530 | dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80); | ||
1531 | |||
1532 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { | ||
1533 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) // Sound Broadcasting mode 1 seg | ||
1534 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (11-P_mode) */ | ||
1535 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode)); | ||
1536 | |||
1537 | else // Sound Broadcasting mode 3 seg | ||
1538 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ | ||
1539 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode)); | ||
1540 | } else | ||
1541 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ | ||
1542 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode)); | ||
1543 | |||
1544 | /* P_dvsy_sync_wait - reuse mode */ | ||
1545 | switch (state->fe.dtv_property_cache.transmission_mode) { | ||
1546 | case TRANSMISSION_MODE_8K: | ||
1547 | mode = 256; | ||
1548 | break; | ||
1549 | case TRANSMISSION_MODE_4K: | ||
1550 | mode = 128; | ||
1551 | break; | ||
1552 | default: | ||
1553 | case TRANSMISSION_MODE_2K: | ||
1554 | mode = 64; | ||
1555 | break; | ||
1556 | } | ||
1557 | if (state->cfg.diversity_delay == 0) | ||
1558 | mode = (mode * (1 << (guard)) * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo | ||
1559 | else | ||
1560 | mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for DVSY-fifo | ||
1561 | mode <<= 4; | ||
1562 | dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode); | ||
1563 | |||
1564 | /* channel estimation fine configuration */ | ||
1565 | switch (max_constellation) { | ||
1566 | case QAM_64: | ||
1567 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | ||
1568 | coeff[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
1569 | coeff[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
1570 | coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
1571 | coeff[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
1572 | //if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1 | ||
1573 | break; | ||
1574 | case QAM_16: | ||
1575 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | ||
1576 | coeff[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
1577 | coeff[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
1578 | coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
1579 | coeff[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
1580 | //if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16))) | ||
1581 | break; | ||
1582 | default: | ||
1583 | ana_gain = 0; // 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level | ||
1584 | coeff[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
1585 | coeff[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
1586 | coeff[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
1587 | coeff[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
1588 | break; | ||
1589 | } | ||
1590 | for (mode = 0; mode < 4; mode++) | ||
1591 | dib8000_write_word(state, 215 + mode, coeff[mode]); | ||
1592 | |||
1593 | // update ana_gain depending on max constellation | ||
1594 | dib8000_write_word(state, 116, ana_gain); | ||
1595 | // update ADC target depending on ana_gain | ||
1596 | if (ana_gain) { // set -16dB ADC target for ana_gain=-1 | ||
1597 | for (i = 0; i < 10; i++) | ||
1598 | dib8000_write_word(state, 80 + i, adc_target_16dB[i]); | ||
1599 | } else { // set -22dB ADC target for ana_gain=0 | ||
1600 | for (i = 0; i < 10; i++) | ||
1601 | dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); | ||
1602 | } | ||
1603 | |||
1604 | // ---- ANA_FE ---- | ||
1605 | if (state->fe.dtv_property_cache.isdbt_sb_mode) { | ||
1606 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 1) // 3-segments | ||
1607 | ana_fe = ana_fe_coeff_3seg; | ||
1608 | else // 1-segment | ||
1609 | ana_fe = ana_fe_coeff_1seg; | ||
1610 | } else | ||
1611 | ana_fe = ana_fe_coeff_13seg; | ||
1612 | |||
1613 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0) | ||
1614 | for (mode = 0; mode < 24; mode++) | ||
1615 | dib8000_write_word(state, 117 + mode, ana_fe[mode]); | ||
1616 | |||
1617 | // ---- CHAN_BLK ---- | ||
1618 | for (i = 0; i < 13; i++) { | ||
1619 | if ((((~seg_diff_mask) >> i) & 1) == 1) { | ||
1620 | P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0)); | ||
1621 | P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0)); | ||
1622 | } | ||
1623 | } | ||
1624 | dib8000_write_word(state, 222, P_cfr_left_edge); // P_cfr_left_edge | ||
1625 | dib8000_write_word(state, 223, P_cfr_right_edge); // P_cfr_right_edge | ||
1626 | // "P_cspu_left_edge" not used => do not care | ||
1627 | // "P_cspu_right_edge" not used => do not care | ||
1628 | |||
1629 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { // ISDB-Tsb | ||
1630 | dib8000_write_word(state, 228, 1); // P_2d_mode_byp=1 | ||
1631 | dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); // P_cspu_win_cut = 0 | ||
1632 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0 // 1-segment | ||
1633 | && state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) { | ||
1634 | //dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0 | ||
1635 | dib8000_write_word(state, 265, 15); // P_equal_noise_sel = 15 | ||
1636 | } | ||
1637 | } else if (state->isdbt_cfg_loaded == 0) { | ||
1638 | dib8000_write_word(state, 228, 0); // default value | ||
1639 | dib8000_write_word(state, 265, 31); // default value | ||
1640 | dib8000_write_word(state, 205, 0x200f); // init value | ||
1641 | } | ||
1642 | // ---- TMCC ---- | ||
1643 | for (i = 0; i < 3; i++) | ||
1644 | tmcc_pow += | ||
1645 | (((state->fe.dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe.dtv_property_cache.layer[i].segment_count); | ||
1646 | // Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); | ||
1647 | // Threshold is set at 1/4 of max power. | ||
1648 | tmcc_pow *= (1 << (9 - 2)); | ||
1649 | |||
1650 | dib8000_write_word(state, 290, tmcc_pow); // P_tmcc_dec_thres_2k | ||
1651 | dib8000_write_word(state, 291, tmcc_pow); // P_tmcc_dec_thres_4k | ||
1652 | dib8000_write_word(state, 292, tmcc_pow); // P_tmcc_dec_thres_8k | ||
1653 | //dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); | ||
1654 | // ---- PHA3 ---- | ||
1655 | |||
1656 | if (state->isdbt_cfg_loaded == 0) | ||
1657 | dib8000_write_word(state, 250, 3285); /*p_2d_hspeed_thr0 */ | ||
1658 | |||
1659 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) | ||
1660 | state->isdbt_cfg_loaded = 0; | ||
1661 | else | ||
1662 | state->isdbt_cfg_loaded = 1; | ||
1663 | |||
1664 | } | ||
1665 | |||
1666 | static int dib8000_autosearch_start(struct dvb_frontend *fe) | ||
1667 | { | ||
1668 | u8 factor; | ||
1669 | u32 value; | ||
1670 | struct dib8000_state *state = fe->demodulator_priv; | ||
1671 | |||
1672 | int slist = 0; | ||
1673 | |||
1674 | state->fe.dtv_property_cache.inversion = 0; | ||
1675 | if (!state->fe.dtv_property_cache.isdbt_sb_mode) | ||
1676 | state->fe.dtv_property_cache.layer[0].segment_count = 13; | ||
1677 | state->fe.dtv_property_cache.layer[0].modulation = QAM_64; | ||
1678 | state->fe.dtv_property_cache.layer[0].fec = FEC_2_3; | ||
1679 | state->fe.dtv_property_cache.layer[0].interleaving = 0; | ||
1680 | |||
1681 | //choose the right list, in sb, always do everything | ||
1682 | if (state->fe.dtv_property_cache.isdbt_sb_mode) { | ||
1683 | state->fe.dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
1684 | state->fe.dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
1685 | slist = 7; | ||
1686 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); | ||
1687 | } else { | ||
1688 | if (state->fe.dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) { | ||
1689 | if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
1690 | slist = 7; | ||
1691 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 to have autosearch start ok with mode2 | ||
1692 | } else | ||
1693 | slist = 3; | ||
1694 | } else { | ||
1695 | if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
1696 | slist = 2; | ||
1697 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | ||
1698 | } else | ||
1699 | slist = 0; | ||
1700 | } | ||
1701 | |||
1702 | if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) | ||
1703 | state->fe.dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
1704 | if (state->fe.dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) | ||
1705 | state->fe.dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
1706 | |||
1707 | dprintk("using list for autosearch : %d", slist); | ||
1708 | dib8000_set_channel(state, (unsigned char)slist, 1); | ||
1709 | //dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | ||
1710 | |||
1711 | factor = 1; | ||
1712 | |||
1713 | //set lock_mask values | ||
1714 | dib8000_write_word(state, 6, 0x4); | ||
1715 | dib8000_write_word(state, 7, 0x8); | ||
1716 | dib8000_write_word(state, 8, 0x1000); | ||
1717 | |||
1718 | //set lock_mask wait time values | ||
1719 | value = 50 * state->cfg.pll->internal * factor; | ||
1720 | dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
1721 | dib8000_write_word(state, 12, (u16) (value & 0xffff)); // lock0 wait time | ||
1722 | value = 100 * state->cfg.pll->internal * factor; | ||
1723 | dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
1724 | dib8000_write_word(state, 14, (u16) (value & 0xffff)); // lock1 wait time | ||
1725 | value = 1000 * state->cfg.pll->internal * factor; | ||
1726 | dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
1727 | dib8000_write_word(state, 16, (u16) (value & 0xffff)); // lock2 wait time | ||
1728 | |||
1729 | value = dib8000_read_word(state, 0); | ||
1730 | dib8000_write_word(state, 0, (u16) ((1 << 15) | value)); | ||
1731 | dib8000_read_word(state, 1284); // reset the INT. n_irq_pending | ||
1732 | dib8000_write_word(state, 0, (u16) value); | ||
1733 | |||
1734 | } | ||
1735 | |||
1736 | return 0; | ||
1737 | } | ||
1738 | |||
1739 | static int dib8000_autosearch_irq(struct dvb_frontend *fe) | ||
1740 | { | ||
1741 | struct dib8000_state *state = fe->demodulator_priv; | ||
1742 | u16 irq_pending = dib8000_read_word(state, 1284); | ||
1743 | |||
1744 | if (irq_pending & 0x1) { // failed | ||
1745 | dprintk("dib8000_autosearch_irq failed"); | ||
1746 | return 1; | ||
1747 | } | ||
1748 | |||
1749 | if (irq_pending & 0x2) { // succeeded | ||
1750 | dprintk("dib8000_autosearch_irq succeeded"); | ||
1751 | return 2; | ||
1752 | } | ||
1753 | |||
1754 | return 0; // still pending | ||
1755 | } | ||
1756 | |||
1757 | static int dib8000_tune(struct dvb_frontend *fe) | ||
1758 | { | ||
1759 | struct dib8000_state *state = fe->demodulator_priv; | ||
1760 | int ret = 0; | ||
1761 | u16 value, mode = fft_to_mode(state); | ||
1762 | |||
1763 | // we are already tuned - just resuming from suspend | ||
1764 | if (state == NULL) | ||
1765 | return -EINVAL; | ||
1766 | |||
1767 | dib8000_set_bandwidth(state, state->fe.dtv_property_cache.bandwidth_hz / 1000); | ||
1768 | dib8000_set_channel(state, 0, 0); | ||
1769 | |||
1770 | // restart demod | ||
1771 | ret |= dib8000_write_word(state, 770, 0x4000); | ||
1772 | ret |= dib8000_write_word(state, 770, 0x0000); | ||
1773 | msleep(45); | ||
1774 | |||
1775 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */ | ||
1776 | /* ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) ); workaround inh_isi stays at 1 */ | ||
1777 | |||
1778 | // never achieved a lock before - wait for timfreq to update | ||
1779 | if (state->timf == 0) { | ||
1780 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { | ||
1781 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) // Sound Broadcasting mode 1 seg | ||
1782 | msleep(300); | ||
1783 | else // Sound Broadcasting mode 3 seg | ||
1784 | msleep(500); | ||
1785 | } else // 13 seg | ||
1786 | msleep(200); | ||
1787 | } | ||
1788 | //dump_reg(state); | ||
1789 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) { | ||
1790 | if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) { // Sound Broadcasting mode 1 seg | ||
1791 | |||
1792 | /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40 alpha to check on board */ | ||
1793 | dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40); | ||
1794 | //dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80); | ||
1795 | |||
1796 | /* P_ctrl_sfreq_step= (12-P_mode) P_ctrl_sfreq_inh =0 P_ctrl_pha_off_max */ | ||
1797 | ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5)); | ||
1798 | |||
1799 | } else { // Sound Broadcasting mode 3 seg | ||
1800 | |||
1801 | /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 alpha to check on board */ | ||
1802 | dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60); | ||
1803 | |||
1804 | ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5)); | ||
1805 | } | ||
1806 | |||
1807 | } else { // 13 seg | ||
1808 | /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 alpha to check on board */ | ||
1809 | dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80); | ||
1810 | |||
1811 | ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5)); | ||
1812 | |||
1813 | } | ||
1814 | |||
1815 | // we achieved a coff_cpil_lock - it's time to update the timf | ||
1816 | if ((dib8000_read_word(state, 568) >> 11) & 0x1) | ||
1817 | dib8000_update_timf(state); | ||
1818 | |||
1819 | //now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start | ||
1820 | dib8000_write_word(state, 6, 0x200); | ||
1821 | |||
1822 | if (state->revision == 0x8002) { | ||
1823 | value = dib8000_read_word(state, 903); | ||
1824 | dib8000_write_word(state, 903, value & ~(1 << 3)); | ||
1825 | msleep(1); | ||
1826 | dib8000_write_word(state, 903, value | (1 << 3)); | ||
1827 | } | ||
1828 | |||
1829 | return ret; | ||
1830 | } | ||
1831 | |||
1832 | static int dib8000_wakeup(struct dvb_frontend *fe) | ||
1833 | { | ||
1834 | struct dib8000_state *state = fe->demodulator_priv; | ||
1835 | |||
1836 | dib8000_set_power_mode(state, DIB8000M_POWER_ALL); | ||
1837 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
1838 | if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | ||
1839 | dprintk("could not start Slow ADC"); | ||
1840 | |||
1841 | return 0; | ||
1842 | } | ||
1843 | |||
1844 | static int dib8000_sleep(struct dvb_frontend *fe) | ||
1845 | { | ||
1846 | struct dib8000_state *st = fe->demodulator_priv; | ||
1847 | if (1) { | ||
1848 | dib8000_set_output_mode(st, OUTMODE_HIGH_Z); | ||
1849 | dib8000_set_power_mode(st, DIB8000M_POWER_INTERFACE_ONLY); | ||
1850 | return dib8000_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(st, DIBX000_ADC_OFF); | ||
1851 | } else { | ||
1852 | |||
1853 | return 0; | ||
1854 | } | ||
1855 | } | ||
1856 | |||
1857 | static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
1858 | { | ||
1859 | struct dib8000_state *state = fe->demodulator_priv; | ||
1860 | u16 i, val = 0; | ||
1861 | |||
1862 | fe->dtv_property_cache.bandwidth_hz = 6000000; | ||
1863 | |||
1864 | fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; | ||
1865 | |||
1866 | val = dib8000_read_word(state, 570); | ||
1867 | fe->dtv_property_cache.inversion = (val & 0x40) >> 6; | ||
1868 | switch ((val & 0x30) >> 4) { | ||
1869 | case 1: | ||
1870 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; | ||
1871 | break; | ||
1872 | case 3: | ||
1873 | default: | ||
1874 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
1875 | break; | ||
1876 | } | ||
1877 | |||
1878 | switch (val & 0x3) { | ||
1879 | case 0: | ||
1880 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; | ||
1881 | dprintk("dib8000_get_frontend GI = 1/32 "); | ||
1882 | break; | ||
1883 | case 1: | ||
1884 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16; | ||
1885 | dprintk("dib8000_get_frontend GI = 1/16 "); | ||
1886 | break; | ||
1887 | case 2: | ||
1888 | dprintk("dib8000_get_frontend GI = 1/8 "); | ||
1889 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
1890 | break; | ||
1891 | case 3: | ||
1892 | dprintk("dib8000_get_frontend GI = 1/4 "); | ||
1893 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4; | ||
1894 | break; | ||
1895 | } | ||
1896 | |||
1897 | val = dib8000_read_word(state, 505); | ||
1898 | fe->dtv_property_cache.isdbt_partial_reception = val & 1; | ||
1899 | dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception); | ||
1900 | |||
1901 | for (i = 0; i < 3; i++) { | ||
1902 | val = dib8000_read_word(state, 493 + i); | ||
1903 | fe->dtv_property_cache.layer[i].segment_count = val & 0x0F; | ||
1904 | dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count); | ||
1905 | |||
1906 | val = dib8000_read_word(state, 499 + i); | ||
1907 | fe->dtv_property_cache.layer[i].interleaving = val & 0x3; | ||
1908 | dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving); | ||
1909 | |||
1910 | val = dib8000_read_word(state, 481 + i); | ||
1911 | switch (val & 0x7) { | ||
1912 | case 1: | ||
1913 | fe->dtv_property_cache.layer[i].fec = FEC_1_2; | ||
1914 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i); | ||
1915 | break; | ||
1916 | case 2: | ||
1917 | fe->dtv_property_cache.layer[i].fec = FEC_2_3; | ||
1918 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i); | ||
1919 | break; | ||
1920 | case 3: | ||
1921 | fe->dtv_property_cache.layer[i].fec = FEC_3_4; | ||
1922 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i); | ||
1923 | break; | ||
1924 | case 5: | ||
1925 | fe->dtv_property_cache.layer[i].fec = FEC_5_6; | ||
1926 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i); | ||
1927 | break; | ||
1928 | default: | ||
1929 | fe->dtv_property_cache.layer[i].fec = FEC_7_8; | ||
1930 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i); | ||
1931 | break; | ||
1932 | } | ||
1933 | |||
1934 | val = dib8000_read_word(state, 487 + i); | ||
1935 | switch (val & 0x3) { | ||
1936 | case 0: | ||
1937 | dprintk("dib8000_get_frontend : Layer %d DQPSK ", i); | ||
1938 | fe->dtv_property_cache.layer[i].modulation = DQPSK; | ||
1939 | break; | ||
1940 | case 1: | ||
1941 | fe->dtv_property_cache.layer[i].modulation = QPSK; | ||
1942 | dprintk("dib8000_get_frontend : Layer %d QPSK ", i); | ||
1943 | break; | ||
1944 | case 2: | ||
1945 | fe->dtv_property_cache.layer[i].modulation = QAM_16; | ||
1946 | dprintk("dib8000_get_frontend : Layer %d QAM16 ", i); | ||
1947 | break; | ||
1948 | case 3: | ||
1949 | default: | ||
1950 | dprintk("dib8000_get_frontend : Layer %d QAM64 ", i); | ||
1951 | fe->dtv_property_cache.layer[i].modulation = QAM_64; | ||
1952 | break; | ||
1953 | } | ||
1954 | } | ||
1955 | return 0; | ||
1956 | } | ||
1957 | |||
1958 | static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
1959 | { | ||
1960 | struct dib8000_state *state = fe->demodulator_priv; | ||
1961 | int time, ret; | ||
1962 | |||
1963 | dib8000_set_output_mode(state, OUTMODE_HIGH_Z); | ||
1964 | |||
1965 | if (fe->ops.tuner_ops.set_params) | ||
1966 | fe->ops.tuner_ops.set_params(fe, fep); | ||
1967 | |||
1968 | /* start up the AGC */ | ||
1969 | state->tune_state = CT_AGC_START; | ||
1970 | do { | ||
1971 | time = dib8000_agc_startup(fe); | ||
1972 | if (time != FE_CALLBACK_TIME_NEVER) | ||
1973 | msleep(time / 10); | ||
1974 | else | ||
1975 | break; | ||
1976 | } while (state->tune_state != CT_AGC_STOP); | ||
1977 | |||
1978 | if (state->fe.dtv_property_cache.frequency == 0) { | ||
1979 | dprintk("dib8000: must at least specify frequency "); | ||
1980 | return 0; | ||
1981 | } | ||
1982 | |||
1983 | if (state->fe.dtv_property_cache.bandwidth_hz == 0) { | ||
1984 | dprintk("dib8000: no bandwidth specified, set to default "); | ||
1985 | state->fe.dtv_property_cache.bandwidth_hz = 6000000; | ||
1986 | } | ||
1987 | |||
1988 | state->tune_state = CT_DEMOD_START; | ||
1989 | |||
1990 | if ((state->fe.dtv_property_cache.delivery_system != SYS_ISDBT) || | ||
1991 | (state->fe.dtv_property_cache.inversion == INVERSION_AUTO) || | ||
1992 | (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) || | ||
1993 | (state->fe.dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) || | ||
1994 | (((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) && | ||
1995 | (state->fe.dtv_property_cache.layer[0].segment_count != 0xff) && | ||
1996 | (state->fe.dtv_property_cache.layer[0].segment_count != 0) && | ||
1997 | ((state->fe.dtv_property_cache.layer[0].modulation == QAM_AUTO) || | ||
1998 | (state->fe.dtv_property_cache.layer[0].fec == FEC_AUTO))) || | ||
1999 | (((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) && | ||
2000 | (state->fe.dtv_property_cache.layer[1].segment_count != 0xff) && | ||
2001 | (state->fe.dtv_property_cache.layer[1].segment_count != 0) && | ||
2002 | ((state->fe.dtv_property_cache.layer[1].modulation == QAM_AUTO) || | ||
2003 | (state->fe.dtv_property_cache.layer[1].fec == FEC_AUTO))) || | ||
2004 | (((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) && | ||
2005 | (state->fe.dtv_property_cache.layer[2].segment_count != 0xff) && | ||
2006 | (state->fe.dtv_property_cache.layer[2].segment_count != 0) && | ||
2007 | ((state->fe.dtv_property_cache.layer[2].modulation == QAM_AUTO) || | ||
2008 | (state->fe.dtv_property_cache.layer[2].fec == FEC_AUTO))) || | ||
2009 | (((state->fe.dtv_property_cache.layer[0].segment_count == 0) || | ||
2010 | ((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) && | ||
2011 | ((state->fe.dtv_property_cache.layer[1].segment_count == 0) || | ||
2012 | ((state->fe.dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) && | ||
2013 | ((state->fe.dtv_property_cache.layer[2].segment_count == 0) || ((state->fe.dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) { | ||
2014 | int i = 800, found; | ||
2015 | |||
2016 | dib8000_set_bandwidth(state, fe->dtv_property_cache.bandwidth_hz / 1000); | ||
2017 | dib8000_autosearch_start(fe); | ||
2018 | do { | ||
2019 | msleep(10); | ||
2020 | found = dib8000_autosearch_irq(fe); | ||
2021 | } while (found == 0 && i--); | ||
2022 | |||
2023 | dprintk("Frequency %d Hz, autosearch returns: %d", fep->frequency, found); | ||
2024 | |||
2025 | if (found == 0 || found == 1) | ||
2026 | return 0; // no channel found | ||
2027 | |||
2028 | dib8000_get_frontend(fe, fep); | ||
2029 | } | ||
2030 | |||
2031 | ret = dib8000_tune(fe); | ||
2032 | |||
2033 | /* make this a config parameter */ | ||
2034 | dib8000_set_output_mode(state, state->cfg.output_mode); | ||
2035 | |||
2036 | return ret; | ||
2037 | } | ||
2038 | |||
2039 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | ||
2040 | { | ||
2041 | struct dib8000_state *state = fe->demodulator_priv; | ||
2042 | u16 lock = dib8000_read_word(state, 568); | ||
2043 | |||
2044 | *stat = 0; | ||
2045 | |||
2046 | if ((lock >> 14) & 1) // AGC | ||
2047 | *stat |= FE_HAS_SIGNAL; | ||
2048 | |||
2049 | if ((lock >> 8) & 1) // Equal | ||
2050 | *stat |= FE_HAS_CARRIER; | ||
2051 | |||
2052 | if ((lock >> 3) & 1) // TMCC_SYNC | ||
2053 | *stat |= FE_HAS_SYNC; | ||
2054 | |||
2055 | if ((lock >> 5) & 7) // FEC MPEG | ||
2056 | *stat |= FE_HAS_LOCK; | ||
2057 | |||
2058 | lock = dib8000_read_word(state, 554); // Viterbi Layer A | ||
2059 | if (lock & 0x01) | ||
2060 | *stat |= FE_HAS_VITERBI; | ||
2061 | |||
2062 | lock = dib8000_read_word(state, 555); // Viterbi Layer B | ||
2063 | if (lock & 0x01) | ||
2064 | *stat |= FE_HAS_VITERBI; | ||
2065 | |||
2066 | lock = dib8000_read_word(state, 556); // Viterbi Layer C | ||
2067 | if (lock & 0x01) | ||
2068 | *stat |= FE_HAS_VITERBI; | ||
2069 | |||
2070 | return 0; | ||
2071 | } | ||
2072 | |||
2073 | static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber) | ||
2074 | { | ||
2075 | struct dib8000_state *state = fe->demodulator_priv; | ||
2076 | *ber = (dib8000_read_word(state, 560) << 16) | dib8000_read_word(state, 561); // 13 segments | ||
2077 | return 0; | ||
2078 | } | ||
2079 | |||
2080 | static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | ||
2081 | { | ||
2082 | struct dib8000_state *state = fe->demodulator_priv; | ||
2083 | *unc = dib8000_read_word(state, 565); // packet error on 13 seg | ||
2084 | return 0; | ||
2085 | } | ||
2086 | |||
2087 | static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | ||
2088 | { | ||
2089 | struct dib8000_state *state = fe->demodulator_priv; | ||
2090 | u16 val = dib8000_read_word(state, 390); | ||
2091 | *strength = 65535 - val; | ||
2092 | return 0; | ||
2093 | } | ||
2094 | |||
2095 | static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) | ||
2096 | { | ||
2097 | struct dib8000_state *state = fe->demodulator_priv; | ||
2098 | u16 val; | ||
2099 | s32 signal_mant, signal_exp, noise_mant, noise_exp; | ||
2100 | u32 result = 0; | ||
2101 | |||
2102 | val = dib8000_read_word(state, 542); | ||
2103 | noise_mant = (val >> 6) & 0xff; | ||
2104 | noise_exp = (val & 0x3f); | ||
2105 | |||
2106 | val = dib8000_read_word(state, 543); | ||
2107 | signal_mant = (val >> 6) & 0xff; | ||
2108 | signal_exp = (val & 0x3f); | ||
2109 | |||
2110 | if ((noise_exp & 0x20) != 0) | ||
2111 | noise_exp -= 0x40; | ||
2112 | if ((signal_exp & 0x20) != 0) | ||
2113 | signal_exp -= 0x40; | ||
2114 | |||
2115 | if (signal_mant != 0) | ||
2116 | result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant); | ||
2117 | else | ||
2118 | result = intlog10(2) * 10 * signal_exp - 100; | ||
2119 | if (noise_mant != 0) | ||
2120 | result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant); | ||
2121 | else | ||
2122 | result -= intlog10(2) * 10 * noise_exp - 100; | ||
2123 | |||
2124 | *snr = result / (1 << 24); | ||
2125 | return 0; | ||
2126 | } | ||
2127 | |||
2128 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) | ||
2129 | { | ||
2130 | int k = 0; | ||
2131 | u8 new_addr = 0; | ||
2132 | struct i2c_device client = {.adap = host }; | ||
2133 | |||
2134 | for (k = no_of_demods - 1; k >= 0; k--) { | ||
2135 | /* designated i2c address */ | ||
2136 | new_addr = first_addr + (k << 1); | ||
2137 | |||
2138 | client.addr = new_addr; | ||
2139 | dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ | ||
2140 | if (dib8000_identify(&client) == 0) { | ||
2141 | dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ | ||
2142 | client.addr = default_addr; | ||
2143 | if (dib8000_identify(&client) == 0) { | ||
2144 | dprintk("#%d: not identified", k); | ||
2145 | return -EINVAL; | ||
2146 | } | ||
2147 | } | ||
2148 | |||
2149 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
2150 | dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6)); | ||
2151 | |||
2152 | /* set new i2c address and force divstart */ | ||
2153 | dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2); | ||
2154 | client.addr = new_addr; | ||
2155 | dib8000_identify(&client); | ||
2156 | |||
2157 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); | ||
2158 | } | ||
2159 | |||
2160 | for (k = 0; k < no_of_demods; k++) { | ||
2161 | new_addr = first_addr | (k << 1); | ||
2162 | client.addr = new_addr; | ||
2163 | |||
2164 | // unforce divstr | ||
2165 | dib8000_i2c_write16(&client, 1285, new_addr << 2); | ||
2166 | |||
2167 | /* deactivate div - it was just for i2c-enumeration */ | ||
2168 | dib8000_i2c_write16(&client, 1286, 0); | ||
2169 | } | ||
2170 | |||
2171 | return 0; | ||
2172 | } | ||
2173 | |||
2174 | EXPORT_SYMBOL(dib8000_i2c_enumeration); | ||
2175 | static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) | ||
2176 | { | ||
2177 | tune->min_delay_ms = 1000; | ||
2178 | tune->step_size = 0; | ||
2179 | tune->max_drift = 0; | ||
2180 | return 0; | ||
2181 | } | ||
2182 | |||
2183 | static void dib8000_release(struct dvb_frontend *fe) | ||
2184 | { | ||
2185 | struct dib8000_state *st = fe->demodulator_priv; | ||
2186 | dibx000_exit_i2c_master(&st->i2c_master); | ||
2187 | kfree(st); | ||
2188 | } | ||
2189 | |||
2190 | struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating) | ||
2191 | { | ||
2192 | struct dib8000_state *st = fe->demodulator_priv; | ||
2193 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
2194 | } | ||
2195 | |||
2196 | EXPORT_SYMBOL(dib8000_get_i2c_master); | ||
2197 | |||
2198 | static const struct dvb_frontend_ops dib8000_ops = { | ||
2199 | .info = { | ||
2200 | .name = "DiBcom 8000 ISDB-T", | ||
2201 | .type = FE_OFDM, | ||
2202 | .frequency_min = 44250000, | ||
2203 | .frequency_max = 867250000, | ||
2204 | .frequency_stepsize = 62500, | ||
2205 | .caps = FE_CAN_INVERSION_AUTO | | ||
2206 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
2207 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
2208 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
2209 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO, | ||
2210 | }, | ||
2211 | |||
2212 | .release = dib8000_release, | ||
2213 | |||
2214 | .init = dib8000_wakeup, | ||
2215 | .sleep = dib8000_sleep, | ||
2216 | |||
2217 | .set_frontend = dib8000_set_frontend, | ||
2218 | .get_tune_settings = dib8000_fe_get_tune_settings, | ||
2219 | .get_frontend = dib8000_get_frontend, | ||
2220 | |||
2221 | .read_status = dib8000_read_status, | ||
2222 | .read_ber = dib8000_read_ber, | ||
2223 | .read_signal_strength = dib8000_read_signal_strength, | ||
2224 | .read_snr = dib8000_read_snr, | ||
2225 | .read_ucblocks = dib8000_read_unc_blocks, | ||
2226 | }; | ||
2227 | |||
2228 | struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) | ||
2229 | { | ||
2230 | struct dvb_frontend *fe; | ||
2231 | struct dib8000_state *state; | ||
2232 | |||
2233 | dprintk("dib8000_attach"); | ||
2234 | |||
2235 | state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL); | ||
2236 | if (state == NULL) | ||
2237 | return NULL; | ||
2238 | |||
2239 | memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); | ||
2240 | state->i2c.adap = i2c_adap; | ||
2241 | state->i2c.addr = i2c_addr; | ||
2242 | state->gpio_val = cfg->gpio_val; | ||
2243 | state->gpio_dir = cfg->gpio_dir; | ||
2244 | |||
2245 | /* Ensure the output mode remains at the previous default if it's | ||
2246 | * not specifically set by the caller. | ||
2247 | */ | ||
2248 | if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK)) | ||
2249 | state->cfg.output_mode = OUTMODE_MPEG2_FIFO; | ||
2250 | |||
2251 | fe = &state->fe; | ||
2252 | fe->demodulator_priv = state; | ||
2253 | memcpy(&state->fe.ops, &dib8000_ops, sizeof(struct dvb_frontend_ops)); | ||
2254 | |||
2255 | state->timf_default = cfg->pll->timf; | ||
2256 | |||
2257 | if (dib8000_identify(&state->i2c) == 0) | ||
2258 | goto error; | ||
2259 | |||
2260 | dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); | ||
2261 | |||
2262 | dib8000_reset(fe); | ||
2263 | |||
2264 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ | ||
2265 | |||
2266 | return fe; | ||
2267 | |||
2268 | error: | ||
2269 | kfree(state); | ||
2270 | return NULL; | ||
2271 | } | ||
2272 | |||
2273 | EXPORT_SYMBOL(dib8000_attach); | ||
2274 | |||
2275 | MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
2276 | MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); | ||
2277 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h new file mode 100644 index 000000000000..a86de340dd54 --- /dev/null +++ b/drivers/media/dvb/frontends/dib8000.h | |||
@@ -0,0 +1,79 @@ | |||
1 | #ifndef DIB8000_H | ||
2 | #define DIB8000_H | ||
3 | |||
4 | #include "dibx000_common.h" | ||
5 | |||
6 | struct dib8000_config { | ||
7 | u8 output_mpeg2_in_188_bytes; | ||
8 | u8 hostbus_diversity; | ||
9 | u8 tuner_is_baseband; | ||
10 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); | ||
11 | |||
12 | u8 agc_config_count; | ||
13 | struct dibx000_agc_config *agc; | ||
14 | struct dibx000_bandwidth_config *pll; | ||
15 | |||
16 | #define DIB8000_GPIO_DEFAULT_DIRECTIONS 0xffff | ||
17 | u16 gpio_dir; | ||
18 | #define DIB8000_GPIO_DEFAULT_VALUES 0x0000 | ||
19 | u16 gpio_val; | ||
20 | #define DIB8000_GPIO_PWM_POS0(v) ((v & 0xf) << 12) | ||
21 | #define DIB8000_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) | ||
22 | #define DIB8000_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) | ||
23 | #define DIB8000_GPIO_PWM_POS3(v) (v & 0xf) | ||
24 | #define DIB8000_GPIO_DEFAULT_PWM_POS 0xffff | ||
25 | u16 gpio_pwm_pos; | ||
26 | u16 pwm_freq_div; | ||
27 | |||
28 | void (*agc_control) (struct dvb_frontend *, u8 before); | ||
29 | |||
30 | u16 drives; | ||
31 | u16 diversity_delay; | ||
32 | u8 div_cfg; | ||
33 | u8 output_mode; | ||
34 | u8 refclksel; | ||
35 | }; | ||
36 | |||
37 | #define DEFAULT_DIB8000_I2C_ADDRESS 18 | ||
38 | |||
39 | #if defined(CONFIG_DVB_DIB8000) || (defined(CONFIG_DVB_DIB8000_MODULE) && defined(MODULE)) | ||
40 | extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg); | ||
41 | extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
42 | |||
43 | extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr); | ||
44 | |||
45 | extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); | ||
46 | extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); | ||
47 | #else | ||
48 | static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) | ||
49 | { | ||
50 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x) | ||
55 | { | ||
56 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
57 | return NULL; | ||
58 | } | ||
59 | |||
60 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) | ||
61 | { | ||
62 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
63 | return -ENODEV; | ||
64 | } | ||
65 | |||
66 | int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | ||
67 | { | ||
68 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
69 | return -ENODEV; | ||
70 | } | ||
71 | |||
72 | int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | ||
73 | { | ||
74 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
75 | return -ENODEV; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index 315e09e95b0c..4efca30d2127 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -15,29 +15,31 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) | |||
15 | (val >> 8) & 0xff, val & 0xff, | 15 | (val >> 8) & 0xff, val & 0xff, |
16 | }; | 16 | }; |
17 | struct i2c_msg msg = { | 17 | struct i2c_msg msg = { |
18 | .addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4 | 18 | .addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4 |
19 | }; | 19 | }; |
20 | return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 20 | return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
21 | } | 21 | } |
22 | 22 | ||
23 | 23 | ||
24 | static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf) | 24 | static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, |
25 | enum dibx000_i2c_interface intf) | ||
25 | { | 26 | { |
26 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { | 27 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { |
27 | dprintk("selecting interface: %d\n",intf); | 28 | dprintk("selecting interface: %d\n", intf); |
28 | mst->selected_interface = intf; | 29 | mst->selected_interface = intf; |
29 | return dibx000_write_word(mst, mst->base_reg + 4, intf); | 30 | return dibx000_write_word(mst, mst->base_reg + 4, intf); |
30 | } | 31 | } |
31 | return 0; | 32 | return 0; |
32 | } | 33 | } |
33 | 34 | ||
34 | static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff) | 35 | static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], |
36 | u8 addr, int onoff) | ||
35 | { | 37 | { |
36 | u16 val; | 38 | u16 val; |
37 | 39 | ||
38 | 40 | ||
39 | if (onoff) | 41 | if (onoff) |
40 | val = addr << 8; // bit 7 = use master or not, if 0, the gate is open | 42 | val = addr << 8; // bit 7 = use master or not, if 0, the gate is open |
41 | else | 43 | else |
42 | val = 1 << 7; | 44 | val = 1 << 7; |
43 | 45 | ||
@@ -45,7 +47,7 @@ static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 ad | |||
45 | val <<= 1; | 47 | val <<= 1; |
46 | 48 | ||
47 | tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); | 49 | tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); |
48 | tx[1] = ( (mst->base_reg + 1) & 0xff); | 50 | tx[1] = ((mst->base_reg + 1) & 0xff); |
49 | tx[2] = val >> 8; | 51 | tx[2] = val >> 8; |
50 | tx[3] = val & 0xff; | 52 | tx[3] = val & 0xff; |
51 | 53 | ||
@@ -57,59 +59,78 @@ static u32 dibx000_i2c_func(struct i2c_adapter *adapter) | |||
57 | return I2C_FUNC_I2C; | 59 | return I2C_FUNC_I2C; |
58 | } | 60 | } |
59 | 61 | ||
60 | static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) | 62 | static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, |
63 | struct i2c_msg msg[], int num) | ||
61 | { | 64 | { |
62 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | 65 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); |
63 | struct i2c_msg m[2 + num]; | 66 | struct i2c_msg m[2 + num]; |
64 | u8 tx_open[4], tx_close[4]; | 67 | u8 tx_open[4], tx_close[4]; |
65 | 68 | ||
66 | memset(m,0, sizeof(struct i2c_msg) * (2 + num)); | 69 | memset(m, 0, sizeof(struct i2c_msg) * (2 + num)); |
67 | 70 | ||
68 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | 71 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); |
69 | 72 | ||
70 | dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); | 73 | dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); |
71 | m[0].addr = mst->i2c_addr; | 74 | m[0].addr = mst->i2c_addr; |
72 | m[0].buf = tx_open; | 75 | m[0].buf = tx_open; |
73 | m[0].len = 4; | 76 | m[0].len = 4; |
74 | 77 | ||
75 | memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); | 78 | memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); |
76 | 79 | ||
77 | dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); | 80 | dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); |
78 | m[num+1].addr = mst->i2c_addr; | 81 | m[num + 1].addr = mst->i2c_addr; |
79 | m[num+1].buf = tx_close; | 82 | m[num + 1].buf = tx_close; |
80 | m[num+1].len = 4; | 83 | m[num + 1].len = 4; |
81 | 84 | ||
82 | return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO; | 85 | return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO; |
83 | } | 86 | } |
84 | 87 | ||
85 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { | 88 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { |
86 | .master_xfer = dibx000_i2c_gated_tuner_xfer, | 89 | .master_xfer = dibx000_i2c_gated_tuner_xfer, |
87 | .functionality = dibx000_i2c_func, | 90 | .functionality = dibx000_i2c_func, |
88 | }; | 91 | }; |
89 | 92 | ||
90 | struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating) | 93 | struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, |
94 | enum dibx000_i2c_interface intf, | ||
95 | int gating) | ||
91 | { | 96 | { |
92 | struct i2c_adapter *i2c = NULL; | 97 | struct i2c_adapter *i2c = NULL; |
93 | 98 | ||
94 | switch (intf) { | 99 | switch (intf) { |
95 | case DIBX000_I2C_INTERFACE_TUNER: | 100 | case DIBX000_I2C_INTERFACE_TUNER: |
96 | if (gating) | 101 | if (gating) |
97 | i2c = &mst->gated_tuner_i2c_adap; | 102 | i2c = &mst->gated_tuner_i2c_adap; |
98 | break; | 103 | break; |
99 | default: | 104 | default: |
100 | printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n"); | 105 | printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n"); |
101 | break; | 106 | break; |
102 | } | 107 | } |
103 | 108 | ||
104 | return i2c; | 109 | return i2c; |
105 | } | 110 | } |
111 | |||
106 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); | 112 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); |
107 | 113 | ||
108 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst) | 114 | void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst) |
115 | { | ||
116 | /* initialize the i2c-master by closing the gate */ | ||
117 | u8 tx[4]; | ||
118 | struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 }; | ||
119 | |||
120 | dibx000_i2c_gate_ctrl(mst, tx, 0, 0); | ||
121 | i2c_transfer(mst->i2c_adap, &m, 1); | ||
122 | mst->selected_interface = 0xff; // the first time force a select of the I2C | ||
123 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | ||
124 | } | ||
125 | |||
126 | EXPORT_SYMBOL(dibx000_reset_i2c_master); | ||
127 | |||
128 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, | ||
129 | struct i2c_algorithm *algo, const char *name, | ||
130 | struct dibx000_i2c_master *mst) | ||
109 | { | 131 | { |
110 | strncpy(i2c_adap->name, name, sizeof(i2c_adap->name)); | 132 | strncpy(i2c_adap->name, name, sizeof(i2c_adap->name)); |
111 | i2c_adap->class = I2C_CLASS_TV_DIGITAL, | 133 | i2c_adap->class = I2C_CLASS_TV_DIGITAL, i2c_adap->algo = algo; |
112 | i2c_adap->algo = algo; | ||
113 | i2c_adap->algo_data = NULL; | 134 | i2c_adap->algo_data = NULL; |
114 | i2c_set_adapdata(i2c_adap, mst); | 135 | i2c_set_adapdata(i2c_adap, mst); |
115 | if (i2c_add_adapter(i2c_adap) < 0) | 136 | if (i2c_add_adapter(i2c_adap) < 0) |
@@ -117,34 +138,40 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm * | |||
117 | return 0; | 138 | return 0; |
118 | } | 139 | } |
119 | 140 | ||
120 | int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr) | 141 | int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, |
142 | struct i2c_adapter *i2c_adap, u8 i2c_addr) | ||
121 | { | 143 | { |
122 | u8 tx[4]; | 144 | u8 tx[4]; |
123 | struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 }; | 145 | struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 }; |
124 | 146 | ||
125 | mst->device_rev = device_rev; | 147 | mst->device_rev = device_rev; |
126 | mst->i2c_adap = i2c_adap; | 148 | mst->i2c_adap = i2c_adap; |
127 | mst->i2c_addr = i2c_addr >> 1; | 149 | mst->i2c_addr = i2c_addr >> 1; |
128 | 150 | ||
129 | if (device_rev == DIB7000P) | 151 | if (device_rev == DIB7000P || device_rev == DIB8000) |
130 | mst->base_reg = 1024; | 152 | mst->base_reg = 1024; |
131 | else | 153 | else |
132 | mst->base_reg = 768; | 154 | mst->base_reg = 768; |
133 | 155 | ||
134 | if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0) | 156 | if (i2c_adapter_init |
135 | printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n"); | 157 | (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, |
158 | "DiBX000 tuner I2C bus", mst) != 0) | ||
159 | printk(KERN_ERR | ||
160 | "DiBX000: could not initialize the tuner i2c_adapter\n"); | ||
136 | 161 | ||
137 | /* initialize the i2c-master by closing the gate */ | 162 | /* initialize the i2c-master by closing the gate */ |
138 | dibx000_i2c_gate_ctrl(mst, tx, 0, 0); | 163 | dibx000_i2c_gate_ctrl(mst, tx, 0, 0); |
139 | 164 | ||
140 | return i2c_transfer(i2c_adap, &m, 1) == 1; | 165 | return i2c_transfer(i2c_adap, &m, 1) == 1; |
141 | } | 166 | } |
167 | |||
142 | EXPORT_SYMBOL(dibx000_init_i2c_master); | 168 | EXPORT_SYMBOL(dibx000_init_i2c_master); |
143 | 169 | ||
144 | void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) | 170 | void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) |
145 | { | 171 | { |
146 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); | 172 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); |
147 | } | 173 | } |
174 | |||
148 | EXPORT_SYMBOL(dibx000_exit_i2c_master); | 175 | EXPORT_SYMBOL(dibx000_exit_i2c_master); |
149 | 176 | ||
150 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 177 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 84e4d5362922..5be10eca07c0 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #define DIBX000_COMMON_H | 2 | #define DIBX000_COMMON_H |
3 | 3 | ||
4 | enum dibx000_i2c_interface { | 4 | enum dibx000_i2c_interface { |
5 | DIBX000_I2C_INTERFACE_TUNER = 0, | 5 | DIBX000_I2C_INTERFACE_TUNER = 0, |
6 | DIBX000_I2C_INTERFACE_GPIO_1_2 = 1, | 6 | DIBX000_I2C_INTERFACE_GPIO_1_2 = 1, |
7 | DIBX000_I2C_INTERFACE_GPIO_3_4 = 2 | 7 | DIBX000_I2C_INTERFACE_GPIO_3_4 = 2 |
8 | }; | 8 | }; |
@@ -12,22 +12,29 @@ struct dibx000_i2c_master { | |||
12 | #define DIB7000 2 | 12 | #define DIB7000 2 |
13 | #define DIB7000P 11 | 13 | #define DIB7000P 11 |
14 | #define DIB7000MC 12 | 14 | #define DIB7000MC 12 |
15 | #define DIB8000 13 | ||
15 | u16 device_rev; | 16 | u16 device_rev; |
16 | 17 | ||
17 | enum dibx000_i2c_interface selected_interface; | 18 | enum dibx000_i2c_interface selected_interface; |
18 | 19 | ||
19 | // struct i2c_adapter tuner_i2c_adap; | 20 | // struct i2c_adapter tuner_i2c_adap; |
20 | struct i2c_adapter gated_tuner_i2c_adap; | 21 | struct i2c_adapter gated_tuner_i2c_adap; |
21 | 22 | ||
22 | struct i2c_adapter *i2c_adap; | 23 | struct i2c_adapter *i2c_adap; |
23 | u8 i2c_addr; | 24 | u8 i2c_addr; |
24 | 25 | ||
25 | u16 base_reg; | 26 | u16 base_reg; |
26 | }; | 27 | }; |
27 | 28 | ||
28 | extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr); | 29 | extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, |
29 | extern struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating); | 30 | u16 device_rev, struct i2c_adapter *i2c_adap, |
31 | u8 i2c_addr); | ||
32 | extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master | ||
33 | *mst, | ||
34 | enum dibx000_i2c_interface | ||
35 | intf, int gating); | ||
30 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | 36 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); |
37 | extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); | ||
31 | 38 | ||
32 | #define BAND_LBAND 0x01 | 39 | #define BAND_LBAND 0x01 |
33 | #define BAND_UHF 0x02 | 40 | #define BAND_UHF 0x02 |
@@ -41,18 +48,18 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | |||
41 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) | 48 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) |
42 | 49 | ||
43 | struct dibx000_agc_config { | 50 | struct dibx000_agc_config { |
44 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ | 51 | /* defines the capabilities of this AGC-setting - using the BAND_-defines */ |
45 | u8 band_caps; | 52 | u8 band_caps; |
46 | 53 | ||
47 | u16 setup; | 54 | u16 setup; |
48 | 55 | ||
49 | u16 inv_gain; | 56 | u16 inv_gain; |
50 | u16 time_stabiliz; | 57 | u16 time_stabiliz; |
51 | 58 | ||
52 | u8 alpha_level; | 59 | u8 alpha_level; |
53 | u16 thlock; | 60 | u16 thlock; |
54 | 61 | ||
55 | u8 wbd_inv; | 62 | u8 wbd_inv; |
56 | u16 wbd_ref; | 63 | u16 wbd_ref; |
57 | u8 wbd_sel; | 64 | u8 wbd_sel; |
58 | u8 wbd_alpha; | 65 | u8 wbd_alpha; |
@@ -92,8 +99,8 @@ struct dibx000_agc_config { | |||
92 | }; | 99 | }; |
93 | 100 | ||
94 | struct dibx000_bandwidth_config { | 101 | struct dibx000_bandwidth_config { |
95 | u32 internal; | 102 | u32 internal; |
96 | u32 sampling; | 103 | u32 sampling; |
97 | 104 | ||
98 | u8 pll_prediv; | 105 | u8 pll_prediv; |
99 | u8 pll_ratio; | 106 | u8 pll_ratio; |
diff --git a/drivers/media/dvb/frontends/lgdt3304.c b/drivers/media/dvb/frontends/lgdt3304.c index eb72a9866c93..e334b5d4e578 100644 --- a/drivers/media/dvb/frontends/lgdt3304.c +++ b/drivers/media/dvb/frontends/lgdt3304.c | |||
@@ -363,6 +363,8 @@ struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, | |||
363 | 363 | ||
364 | struct lgdt3304_state *state; | 364 | struct lgdt3304_state *state; |
365 | state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL); | 365 | state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL); |
366 | if (state == NULL) | ||
367 | return NULL; | ||
366 | state->addr = config->i2c_address; | 368 | state->addr = config->i2c_address; |
367 | state->i2c = i2c; | 369 | state->i2c = i2c; |
368 | 370 | ||
diff --git a/drivers/media/dvb/frontends/s921_module.c b/drivers/media/dvb/frontends/s921_module.c index 3f5a0e1dfdf5..3156b64cfc96 100644 --- a/drivers/media/dvb/frontends/s921_module.c +++ b/drivers/media/dvb/frontends/s921_module.c | |||
@@ -169,6 +169,8 @@ struct dvb_frontend* s921_attach(const struct s921_config *config, | |||
169 | 169 | ||
170 | struct s921_state *state; | 170 | struct s921_state *state; |
171 | state = kzalloc(sizeof(struct s921_state), GFP_KERNEL); | 171 | state = kzalloc(sizeof(struct s921_state), GFP_KERNEL); |
172 | if (state == NULL) | ||
173 | return NULL; | ||
172 | 174 | ||
173 | state->addr = config->i2c_address; | 175 | state->addr = config->i2c_address; |
174 | state->i2c = i2c; | 176 | state->i2c = i2c; |
diff --git a/drivers/media/dvb/pt1/Kconfig b/drivers/media/dvb/pt1/Kconfig new file mode 100644 index 000000000000..24501d5bf70d --- /dev/null +++ b/drivers/media/dvb/pt1/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config DVB_PT1 | ||
2 | tristate "PT1 cards" | ||
3 | depends on DVB_CORE && PCI && I2C | ||
4 | help | ||
5 | Support for Earthsoft PT1 PCI cards. | ||
6 | |||
7 | Since these cards have no MPEG decoder onboard, they transmit | ||
8 | only compressed MPEG data over the PCI bus, so you need | ||
9 | an external software decoder to watch TV on your computer. | ||
10 | |||
11 | Say Y or M if you own such a device and want to use it. | ||
12 | |||
diff --git a/drivers/media/dvb/pt1/Makefile b/drivers/media/dvb/pt1/Makefile new file mode 100644 index 000000000000..a66da17bbe31 --- /dev/null +++ b/drivers/media/dvb/pt1/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o | ||
2 | |||
3 | obj-$(CONFIG_DVB_PT1) += earth-pt1.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends | ||
diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c new file mode 100644 index 000000000000..8ffbcecad931 --- /dev/null +++ b/drivers/media/dvb/pt1/pt1.c | |||
@@ -0,0 +1,1056 @@ | |||
1 | /* | ||
2 | * driver for Earthsoft PT1 | ||
3 | * | ||
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | ||
5 | * | ||
6 | * based on pt1dvr - http://pt1dvr.sourceforge.jp/ | ||
7 | * by Tomoaki Ishikawa <tomy@users.sourceforge.jp> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/kthread.h> | ||
28 | #include <linux/freezer.h> | ||
29 | |||
30 | #include "dvbdev.h" | ||
31 | #include "dvb_demux.h" | ||
32 | #include "dmxdev.h" | ||
33 | #include "dvb_net.h" | ||
34 | #include "dvb_frontend.h" | ||
35 | |||
36 | #include "va1j5jf8007t.h" | ||
37 | #include "va1j5jf8007s.h" | ||
38 | |||
39 | #define DRIVER_NAME "earth-pt1" | ||
40 | |||
41 | #define PT1_PAGE_SHIFT 12 | ||
42 | #define PT1_PAGE_SIZE (1 << PT1_PAGE_SHIFT) | ||
43 | #define PT1_NR_UPACKETS 1024 | ||
44 | #define PT1_NR_BUFS 511 | ||
45 | |||
46 | struct pt1_buffer_page { | ||
47 | __le32 upackets[PT1_NR_UPACKETS]; | ||
48 | }; | ||
49 | |||
50 | struct pt1_table_page { | ||
51 | __le32 next_pfn; | ||
52 | __le32 buf_pfns[PT1_NR_BUFS]; | ||
53 | }; | ||
54 | |||
55 | struct pt1_buffer { | ||
56 | struct pt1_buffer_page *page; | ||
57 | dma_addr_t addr; | ||
58 | }; | ||
59 | |||
60 | struct pt1_table { | ||
61 | struct pt1_table_page *page; | ||
62 | dma_addr_t addr; | ||
63 | struct pt1_buffer bufs[PT1_NR_BUFS]; | ||
64 | }; | ||
65 | |||
66 | #define PT1_NR_ADAPS 4 | ||
67 | |||
68 | struct pt1_adapter; | ||
69 | |||
70 | struct pt1 { | ||
71 | struct pci_dev *pdev; | ||
72 | void __iomem *regs; | ||
73 | struct i2c_adapter i2c_adap; | ||
74 | int i2c_running; | ||
75 | struct pt1_adapter *adaps[PT1_NR_ADAPS]; | ||
76 | struct pt1_table *tables; | ||
77 | struct task_struct *kthread; | ||
78 | }; | ||
79 | |||
80 | struct pt1_adapter { | ||
81 | struct pt1 *pt1; | ||
82 | int index; | ||
83 | |||
84 | u8 *buf; | ||
85 | int upacket_count; | ||
86 | int packet_count; | ||
87 | |||
88 | struct dvb_adapter adap; | ||
89 | struct dvb_demux demux; | ||
90 | int users; | ||
91 | struct dmxdev dmxdev; | ||
92 | struct dvb_net net; | ||
93 | struct dvb_frontend *fe; | ||
94 | int (*orig_set_voltage)(struct dvb_frontend *fe, | ||
95 | fe_sec_voltage_t voltage); | ||
96 | }; | ||
97 | |||
98 | #define pt1_printk(level, pt1, format, arg...) \ | ||
99 | dev_printk(level, &(pt1)->pdev->dev, format, ##arg) | ||
100 | |||
101 | static void pt1_write_reg(struct pt1 *pt1, int reg, u32 data) | ||
102 | { | ||
103 | writel(data, pt1->regs + reg * 4); | ||
104 | } | ||
105 | |||
106 | static u32 pt1_read_reg(struct pt1 *pt1, int reg) | ||
107 | { | ||
108 | return readl(pt1->regs + reg * 4); | ||
109 | } | ||
110 | |||
111 | static int pt1_nr_tables = 64; | ||
112 | module_param_named(nr_tables, pt1_nr_tables, int, 0); | ||
113 | |||
114 | static void pt1_increment_table_count(struct pt1 *pt1) | ||
115 | { | ||
116 | pt1_write_reg(pt1, 0, 0x00000020); | ||
117 | } | ||
118 | |||
119 | static void pt1_init_table_count(struct pt1 *pt1) | ||
120 | { | ||
121 | pt1_write_reg(pt1, 0, 0x00000010); | ||
122 | } | ||
123 | |||
124 | static void pt1_register_tables(struct pt1 *pt1, u32 first_pfn) | ||
125 | { | ||
126 | pt1_write_reg(pt1, 5, first_pfn); | ||
127 | pt1_write_reg(pt1, 0, 0x0c000040); | ||
128 | } | ||
129 | |||
130 | static void pt1_unregister_tables(struct pt1 *pt1) | ||
131 | { | ||
132 | pt1_write_reg(pt1, 0, 0x08080000); | ||
133 | } | ||
134 | |||
135 | static int pt1_sync(struct pt1 *pt1) | ||
136 | { | ||
137 | int i; | ||
138 | for (i = 0; i < 57; i++) { | ||
139 | if (pt1_read_reg(pt1, 0) & 0x20000000) | ||
140 | return 0; | ||
141 | pt1_write_reg(pt1, 0, 0x00000008); | ||
142 | } | ||
143 | pt1_printk(KERN_ERR, pt1, "could not sync\n"); | ||
144 | return -EIO; | ||
145 | } | ||
146 | |||
147 | static u64 pt1_identify(struct pt1 *pt1) | ||
148 | { | ||
149 | int i; | ||
150 | u64 id; | ||
151 | id = 0; | ||
152 | for (i = 0; i < 57; i++) { | ||
153 | id |= (u64)(pt1_read_reg(pt1, 0) >> 30 & 1) << i; | ||
154 | pt1_write_reg(pt1, 0, 0x00000008); | ||
155 | } | ||
156 | return id; | ||
157 | } | ||
158 | |||
159 | static int pt1_unlock(struct pt1 *pt1) | ||
160 | { | ||
161 | int i; | ||
162 | pt1_write_reg(pt1, 0, 0x00000008); | ||
163 | for (i = 0; i < 3; i++) { | ||
164 | if (pt1_read_reg(pt1, 0) & 0x80000000) | ||
165 | return 0; | ||
166 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
167 | } | ||
168 | pt1_printk(KERN_ERR, pt1, "could not unlock\n"); | ||
169 | return -EIO; | ||
170 | } | ||
171 | |||
172 | static int pt1_reset_pci(struct pt1 *pt1) | ||
173 | { | ||
174 | int i; | ||
175 | pt1_write_reg(pt1, 0, 0x01010000); | ||
176 | pt1_write_reg(pt1, 0, 0x01000000); | ||
177 | for (i = 0; i < 10; i++) { | ||
178 | if (pt1_read_reg(pt1, 0) & 0x00000001) | ||
179 | return 0; | ||
180 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
181 | } | ||
182 | pt1_printk(KERN_ERR, pt1, "could not reset PCI\n"); | ||
183 | return -EIO; | ||
184 | } | ||
185 | |||
186 | static int pt1_reset_ram(struct pt1 *pt1) | ||
187 | { | ||
188 | int i; | ||
189 | pt1_write_reg(pt1, 0, 0x02020000); | ||
190 | pt1_write_reg(pt1, 0, 0x02000000); | ||
191 | for (i = 0; i < 10; i++) { | ||
192 | if (pt1_read_reg(pt1, 0) & 0x00000002) | ||
193 | return 0; | ||
194 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
195 | } | ||
196 | pt1_printk(KERN_ERR, pt1, "could not reset RAM\n"); | ||
197 | return -EIO; | ||
198 | } | ||
199 | |||
200 | static int pt1_do_enable_ram(struct pt1 *pt1) | ||
201 | { | ||
202 | int i, j; | ||
203 | u32 status; | ||
204 | status = pt1_read_reg(pt1, 0) & 0x00000004; | ||
205 | pt1_write_reg(pt1, 0, 0x00000002); | ||
206 | for (i = 0; i < 10; i++) { | ||
207 | for (j = 0; j < 1024; j++) { | ||
208 | if ((pt1_read_reg(pt1, 0) & 0x00000004) != status) | ||
209 | return 0; | ||
210 | } | ||
211 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
212 | } | ||
213 | pt1_printk(KERN_ERR, pt1, "could not enable RAM\n"); | ||
214 | return -EIO; | ||
215 | } | ||
216 | |||
217 | static int pt1_enable_ram(struct pt1 *pt1) | ||
218 | { | ||
219 | int i, ret; | ||
220 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
221 | for (i = 0; i < 10; i++) { | ||
222 | ret = pt1_do_enable_ram(pt1); | ||
223 | if (ret < 0) | ||
224 | return ret; | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static void pt1_disable_ram(struct pt1 *pt1) | ||
230 | { | ||
231 | pt1_write_reg(pt1, 0, 0x0b0b0000); | ||
232 | } | ||
233 | |||
234 | static void pt1_set_stream(struct pt1 *pt1, int index, int enabled) | ||
235 | { | ||
236 | pt1_write_reg(pt1, 2, 1 << (index + 8) | enabled << index); | ||
237 | } | ||
238 | |||
239 | static void pt1_init_streams(struct pt1 *pt1) | ||
240 | { | ||
241 | int i; | ||
242 | for (i = 0; i < PT1_NR_ADAPS; i++) | ||
243 | pt1_set_stream(pt1, i, 0); | ||
244 | } | ||
245 | |||
246 | static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page) | ||
247 | { | ||
248 | u32 upacket; | ||
249 | int i; | ||
250 | int index; | ||
251 | struct pt1_adapter *adap; | ||
252 | int offset; | ||
253 | u8 *buf; | ||
254 | |||
255 | if (!page->upackets[PT1_NR_UPACKETS - 1]) | ||
256 | return 0; | ||
257 | |||
258 | for (i = 0; i < PT1_NR_UPACKETS; i++) { | ||
259 | upacket = le32_to_cpu(page->upackets[i]); | ||
260 | index = (upacket >> 29) - 1; | ||
261 | if (index < 0 || index >= PT1_NR_ADAPS) | ||
262 | continue; | ||
263 | |||
264 | adap = pt1->adaps[index]; | ||
265 | if (upacket >> 25 & 1) | ||
266 | adap->upacket_count = 0; | ||
267 | else if (!adap->upacket_count) | ||
268 | continue; | ||
269 | |||
270 | buf = adap->buf; | ||
271 | offset = adap->packet_count * 188 + adap->upacket_count * 3; | ||
272 | buf[offset] = upacket >> 16; | ||
273 | buf[offset + 1] = upacket >> 8; | ||
274 | if (adap->upacket_count != 62) | ||
275 | buf[offset + 2] = upacket; | ||
276 | |||
277 | if (++adap->upacket_count >= 63) { | ||
278 | adap->upacket_count = 0; | ||
279 | if (++adap->packet_count >= 21) { | ||
280 | dvb_dmx_swfilter_packets(&adap->demux, buf, 21); | ||
281 | adap->packet_count = 0; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | page->upackets[PT1_NR_UPACKETS - 1] = 0; | ||
287 | return 1; | ||
288 | } | ||
289 | |||
290 | static int pt1_thread(void *data) | ||
291 | { | ||
292 | struct pt1 *pt1; | ||
293 | int table_index; | ||
294 | int buf_index; | ||
295 | struct pt1_buffer_page *page; | ||
296 | |||
297 | pt1 = data; | ||
298 | set_freezable(); | ||
299 | |||
300 | table_index = 0; | ||
301 | buf_index = 0; | ||
302 | |||
303 | while (!kthread_should_stop()) { | ||
304 | try_to_freeze(); | ||
305 | |||
306 | page = pt1->tables[table_index].bufs[buf_index].page; | ||
307 | if (!pt1_filter(pt1, page)) { | ||
308 | schedule_timeout_interruptible((HZ + 999) / 1000); | ||
309 | continue; | ||
310 | } | ||
311 | |||
312 | if (++buf_index >= PT1_NR_BUFS) { | ||
313 | pt1_increment_table_count(pt1); | ||
314 | buf_index = 0; | ||
315 | if (++table_index >= pt1_nr_tables) | ||
316 | table_index = 0; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static void pt1_free_page(struct pt1 *pt1, void *page, dma_addr_t addr) | ||
324 | { | ||
325 | dma_free_coherent(&pt1->pdev->dev, PT1_PAGE_SIZE, page, addr); | ||
326 | } | ||
327 | |||
328 | static void *pt1_alloc_page(struct pt1 *pt1, dma_addr_t *addrp, u32 *pfnp) | ||
329 | { | ||
330 | void *page; | ||
331 | dma_addr_t addr; | ||
332 | |||
333 | page = dma_alloc_coherent(&pt1->pdev->dev, PT1_PAGE_SIZE, &addr, | ||
334 | GFP_KERNEL); | ||
335 | if (page == NULL) | ||
336 | return NULL; | ||
337 | |||
338 | BUG_ON(addr & (PT1_PAGE_SIZE - 1)); | ||
339 | BUG_ON(addr >> PT1_PAGE_SHIFT >> 31 >> 1); | ||
340 | |||
341 | *addrp = addr; | ||
342 | *pfnp = addr >> PT1_PAGE_SHIFT; | ||
343 | return page; | ||
344 | } | ||
345 | |||
346 | static void pt1_cleanup_buffer(struct pt1 *pt1, struct pt1_buffer *buf) | ||
347 | { | ||
348 | pt1_free_page(pt1, buf->page, buf->addr); | ||
349 | } | ||
350 | |||
351 | static int | ||
352 | pt1_init_buffer(struct pt1 *pt1, struct pt1_buffer *buf, u32 *pfnp) | ||
353 | { | ||
354 | struct pt1_buffer_page *page; | ||
355 | dma_addr_t addr; | ||
356 | |||
357 | page = pt1_alloc_page(pt1, &addr, pfnp); | ||
358 | if (page == NULL) | ||
359 | return -ENOMEM; | ||
360 | |||
361 | page->upackets[PT1_NR_UPACKETS - 1] = 0; | ||
362 | |||
363 | buf->page = page; | ||
364 | buf->addr = addr; | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static void pt1_cleanup_table(struct pt1 *pt1, struct pt1_table *table) | ||
369 | { | ||
370 | int i; | ||
371 | |||
372 | for (i = 0; i < PT1_NR_BUFS; i++) | ||
373 | pt1_cleanup_buffer(pt1, &table->bufs[i]); | ||
374 | |||
375 | pt1_free_page(pt1, table->page, table->addr); | ||
376 | } | ||
377 | |||
378 | static int | ||
379 | pt1_init_table(struct pt1 *pt1, struct pt1_table *table, u32 *pfnp) | ||
380 | { | ||
381 | struct pt1_table_page *page; | ||
382 | dma_addr_t addr; | ||
383 | int i, ret; | ||
384 | u32 buf_pfn; | ||
385 | |||
386 | page = pt1_alloc_page(pt1, &addr, pfnp); | ||
387 | if (page == NULL) | ||
388 | return -ENOMEM; | ||
389 | |||
390 | for (i = 0; i < PT1_NR_BUFS; i++) { | ||
391 | ret = pt1_init_buffer(pt1, &table->bufs[i], &buf_pfn); | ||
392 | if (ret < 0) | ||
393 | goto err; | ||
394 | |||
395 | page->buf_pfns[i] = cpu_to_le32(buf_pfn); | ||
396 | } | ||
397 | |||
398 | pt1_increment_table_count(pt1); | ||
399 | table->page = page; | ||
400 | table->addr = addr; | ||
401 | return 0; | ||
402 | |||
403 | err: | ||
404 | while (i--) | ||
405 | pt1_cleanup_buffer(pt1, &table->bufs[i]); | ||
406 | |||
407 | pt1_free_page(pt1, page, addr); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | static void pt1_cleanup_tables(struct pt1 *pt1) | ||
412 | { | ||
413 | struct pt1_table *tables; | ||
414 | int i; | ||
415 | |||
416 | tables = pt1->tables; | ||
417 | pt1_unregister_tables(pt1); | ||
418 | |||
419 | for (i = 0; i < pt1_nr_tables; i++) | ||
420 | pt1_cleanup_table(pt1, &tables[i]); | ||
421 | |||
422 | vfree(tables); | ||
423 | } | ||
424 | |||
425 | static int pt1_init_tables(struct pt1 *pt1) | ||
426 | { | ||
427 | struct pt1_table *tables; | ||
428 | int i, ret; | ||
429 | u32 first_pfn, pfn; | ||
430 | |||
431 | tables = vmalloc(sizeof(struct pt1_table) * pt1_nr_tables); | ||
432 | if (tables == NULL) | ||
433 | return -ENOMEM; | ||
434 | |||
435 | pt1_init_table_count(pt1); | ||
436 | |||
437 | i = 0; | ||
438 | if (pt1_nr_tables) { | ||
439 | ret = pt1_init_table(pt1, &tables[0], &first_pfn); | ||
440 | if (ret) | ||
441 | goto err; | ||
442 | i++; | ||
443 | } | ||
444 | |||
445 | while (i < pt1_nr_tables) { | ||
446 | ret = pt1_init_table(pt1, &tables[i], &pfn); | ||
447 | if (ret) | ||
448 | goto err; | ||
449 | tables[i - 1].page->next_pfn = cpu_to_le32(pfn); | ||
450 | i++; | ||
451 | } | ||
452 | |||
453 | tables[pt1_nr_tables - 1].page->next_pfn = cpu_to_le32(first_pfn); | ||
454 | |||
455 | pt1_register_tables(pt1, first_pfn); | ||
456 | pt1->tables = tables; | ||
457 | return 0; | ||
458 | |||
459 | err: | ||
460 | while (i--) | ||
461 | pt1_cleanup_table(pt1, &tables[i]); | ||
462 | |||
463 | vfree(tables); | ||
464 | return ret; | ||
465 | } | ||
466 | |||
467 | static int pt1_start_feed(struct dvb_demux_feed *feed) | ||
468 | { | ||
469 | struct pt1_adapter *adap; | ||
470 | adap = container_of(feed->demux, struct pt1_adapter, demux); | ||
471 | if (!adap->users++) | ||
472 | pt1_set_stream(adap->pt1, adap->index, 1); | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int pt1_stop_feed(struct dvb_demux_feed *feed) | ||
477 | { | ||
478 | struct pt1_adapter *adap; | ||
479 | adap = container_of(feed->demux, struct pt1_adapter, demux); | ||
480 | if (!--adap->users) | ||
481 | pt1_set_stream(adap->pt1, adap->index, 0); | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static void | ||
486 | pt1_set_power(struct pt1 *pt1, int power, int lnb, int reset) | ||
487 | { | ||
488 | pt1_write_reg(pt1, 1, power | lnb << 1 | !reset << 3); | ||
489 | } | ||
490 | |||
491 | static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
492 | { | ||
493 | struct pt1_adapter *adap; | ||
494 | int lnb; | ||
495 | |||
496 | adap = container_of(fe->dvb, struct pt1_adapter, adap); | ||
497 | |||
498 | switch (voltage) { | ||
499 | case SEC_VOLTAGE_13: /* actually 11V */ | ||
500 | lnb = 2; | ||
501 | break; | ||
502 | case SEC_VOLTAGE_18: /* actually 15V */ | ||
503 | lnb = 3; | ||
504 | break; | ||
505 | case SEC_VOLTAGE_OFF: | ||
506 | lnb = 0; | ||
507 | break; | ||
508 | default: | ||
509 | return -EINVAL; | ||
510 | } | ||
511 | |||
512 | pt1_set_power(adap->pt1, 1, lnb, 0); | ||
513 | |||
514 | if (adap->orig_set_voltage) | ||
515 | return adap->orig_set_voltage(fe, voltage); | ||
516 | else | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static void pt1_free_adapter(struct pt1_adapter *adap) | ||
521 | { | ||
522 | dvb_unregister_frontend(adap->fe); | ||
523 | dvb_net_release(&adap->net); | ||
524 | adap->demux.dmx.close(&adap->demux.dmx); | ||
525 | dvb_dmxdev_release(&adap->dmxdev); | ||
526 | dvb_dmx_release(&adap->demux); | ||
527 | dvb_unregister_adapter(&adap->adap); | ||
528 | free_page((unsigned long)adap->buf); | ||
529 | kfree(adap); | ||
530 | } | ||
531 | |||
532 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
533 | |||
534 | static struct pt1_adapter * | ||
535 | pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) | ||
536 | { | ||
537 | struct pt1_adapter *adap; | ||
538 | void *buf; | ||
539 | struct dvb_adapter *dvb_adap; | ||
540 | struct dvb_demux *demux; | ||
541 | struct dmxdev *dmxdev; | ||
542 | int ret; | ||
543 | |||
544 | adap = kzalloc(sizeof(struct pt1_adapter), GFP_KERNEL); | ||
545 | if (!adap) { | ||
546 | ret = -ENOMEM; | ||
547 | goto err; | ||
548 | } | ||
549 | |||
550 | adap->pt1 = pt1; | ||
551 | |||
552 | adap->orig_set_voltage = fe->ops.set_voltage; | ||
553 | fe->ops.set_voltage = pt1_set_voltage; | ||
554 | |||
555 | buf = (u8 *)__get_free_page(GFP_KERNEL); | ||
556 | if (!buf) { | ||
557 | ret = -ENOMEM; | ||
558 | goto err_kfree; | ||
559 | } | ||
560 | |||
561 | adap->buf = buf; | ||
562 | adap->upacket_count = 0; | ||
563 | adap->packet_count = 0; | ||
564 | |||
565 | dvb_adap = &adap->adap; | ||
566 | dvb_adap->priv = adap; | ||
567 | ret = dvb_register_adapter(dvb_adap, DRIVER_NAME, THIS_MODULE, | ||
568 | &pt1->pdev->dev, adapter_nr); | ||
569 | if (ret < 0) | ||
570 | goto err_free_page; | ||
571 | |||
572 | demux = &adap->demux; | ||
573 | demux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
574 | demux->priv = adap; | ||
575 | demux->feednum = 256; | ||
576 | demux->filternum = 256; | ||
577 | demux->start_feed = pt1_start_feed; | ||
578 | demux->stop_feed = pt1_stop_feed; | ||
579 | demux->write_to_decoder = NULL; | ||
580 | ret = dvb_dmx_init(demux); | ||
581 | if (ret < 0) | ||
582 | goto err_unregister_adapter; | ||
583 | |||
584 | dmxdev = &adap->dmxdev; | ||
585 | dmxdev->filternum = 256; | ||
586 | dmxdev->demux = &demux->dmx; | ||
587 | dmxdev->capabilities = 0; | ||
588 | ret = dvb_dmxdev_init(dmxdev, dvb_adap); | ||
589 | if (ret < 0) | ||
590 | goto err_dmx_release; | ||
591 | |||
592 | dvb_net_init(dvb_adap, &adap->net, &demux->dmx); | ||
593 | |||
594 | ret = dvb_register_frontend(dvb_adap, fe); | ||
595 | if (ret < 0) | ||
596 | goto err_net_release; | ||
597 | adap->fe = fe; | ||
598 | |||
599 | return adap; | ||
600 | |||
601 | err_net_release: | ||
602 | dvb_net_release(&adap->net); | ||
603 | adap->demux.dmx.close(&adap->demux.dmx); | ||
604 | dvb_dmxdev_release(&adap->dmxdev); | ||
605 | err_dmx_release: | ||
606 | dvb_dmx_release(demux); | ||
607 | err_unregister_adapter: | ||
608 | dvb_unregister_adapter(dvb_adap); | ||
609 | err_free_page: | ||
610 | free_page((unsigned long)buf); | ||
611 | err_kfree: | ||
612 | kfree(adap); | ||
613 | err: | ||
614 | return ERR_PTR(ret); | ||
615 | } | ||
616 | |||
617 | static void pt1_cleanup_adapters(struct pt1 *pt1) | ||
618 | { | ||
619 | int i; | ||
620 | for (i = 0; i < PT1_NR_ADAPS; i++) | ||
621 | pt1_free_adapter(pt1->adaps[i]); | ||
622 | } | ||
623 | |||
624 | struct pt1_config { | ||
625 | struct va1j5jf8007s_config va1j5jf8007s_config; | ||
626 | struct va1j5jf8007t_config va1j5jf8007t_config; | ||
627 | }; | ||
628 | |||
629 | static const struct pt1_config pt1_configs[2] = { | ||
630 | { | ||
631 | { .demod_address = 0x1b }, | ||
632 | { .demod_address = 0x1a }, | ||
633 | }, { | ||
634 | { .demod_address = 0x19 }, | ||
635 | { .demod_address = 0x18 }, | ||
636 | }, | ||
637 | }; | ||
638 | |||
639 | static int pt1_init_adapters(struct pt1 *pt1) | ||
640 | { | ||
641 | int i, j; | ||
642 | struct i2c_adapter *i2c_adap; | ||
643 | const struct pt1_config *config; | ||
644 | struct dvb_frontend *fe[4]; | ||
645 | struct pt1_adapter *adap; | ||
646 | int ret; | ||
647 | |||
648 | i = 0; | ||
649 | j = 0; | ||
650 | |||
651 | i2c_adap = &pt1->i2c_adap; | ||
652 | do { | ||
653 | config = &pt1_configs[i / 2]; | ||
654 | |||
655 | fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config, | ||
656 | i2c_adap); | ||
657 | if (!fe[i]) { | ||
658 | ret = -ENODEV; /* This does not sound nice... */ | ||
659 | goto err; | ||
660 | } | ||
661 | i++; | ||
662 | |||
663 | fe[i] = va1j5jf8007t_attach(&config->va1j5jf8007t_config, | ||
664 | i2c_adap); | ||
665 | if (!fe[i]) { | ||
666 | ret = -ENODEV; | ||
667 | goto err; | ||
668 | } | ||
669 | i++; | ||
670 | |||
671 | ret = va1j5jf8007s_prepare(fe[i - 2]); | ||
672 | if (ret < 0) | ||
673 | goto err; | ||
674 | |||
675 | ret = va1j5jf8007t_prepare(fe[i - 1]); | ||
676 | if (ret < 0) | ||
677 | goto err; | ||
678 | |||
679 | } while (i < 4); | ||
680 | |||
681 | do { | ||
682 | adap = pt1_alloc_adapter(pt1, fe[j]); | ||
683 | if (IS_ERR(adap)) | ||
684 | goto err; | ||
685 | adap->index = j; | ||
686 | pt1->adaps[j] = adap; | ||
687 | } while (++j < 4); | ||
688 | |||
689 | return 0; | ||
690 | |||
691 | err: | ||
692 | while (i-- > j) | ||
693 | fe[i]->ops.release(fe[i]); | ||
694 | |||
695 | while (j--) | ||
696 | pt1_free_adapter(pt1->adaps[j]); | ||
697 | |||
698 | return ret; | ||
699 | } | ||
700 | |||
701 | static void pt1_i2c_emit(struct pt1 *pt1, int addr, int busy, int read_enable, | ||
702 | int clock, int data, int next_addr) | ||
703 | { | ||
704 | pt1_write_reg(pt1, 4, addr << 18 | busy << 13 | read_enable << 12 | | ||
705 | !clock << 11 | !data << 10 | next_addr); | ||
706 | } | ||
707 | |||
708 | static void pt1_i2c_write_bit(struct pt1 *pt1, int addr, int *addrp, int data) | ||
709 | { | ||
710 | pt1_i2c_emit(pt1, addr, 1, 0, 0, data, addr + 1); | ||
711 | pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, data, addr + 2); | ||
712 | pt1_i2c_emit(pt1, addr + 2, 1, 0, 0, data, addr + 3); | ||
713 | *addrp = addr + 3; | ||
714 | } | ||
715 | |||
716 | static void pt1_i2c_read_bit(struct pt1 *pt1, int addr, int *addrp) | ||
717 | { | ||
718 | pt1_i2c_emit(pt1, addr, 1, 0, 0, 1, addr + 1); | ||
719 | pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 1, addr + 2); | ||
720 | pt1_i2c_emit(pt1, addr + 2, 1, 1, 1, 1, addr + 3); | ||
721 | pt1_i2c_emit(pt1, addr + 3, 1, 0, 0, 1, addr + 4); | ||
722 | *addrp = addr + 4; | ||
723 | } | ||
724 | |||
725 | static void pt1_i2c_write_byte(struct pt1 *pt1, int addr, int *addrp, int data) | ||
726 | { | ||
727 | int i; | ||
728 | for (i = 0; i < 8; i++) | ||
729 | pt1_i2c_write_bit(pt1, addr, &addr, data >> (7 - i) & 1); | ||
730 | pt1_i2c_write_bit(pt1, addr, &addr, 1); | ||
731 | *addrp = addr; | ||
732 | } | ||
733 | |||
734 | static void pt1_i2c_read_byte(struct pt1 *pt1, int addr, int *addrp, int last) | ||
735 | { | ||
736 | int i; | ||
737 | for (i = 0; i < 8; i++) | ||
738 | pt1_i2c_read_bit(pt1, addr, &addr); | ||
739 | pt1_i2c_write_bit(pt1, addr, &addr, last); | ||
740 | *addrp = addr; | ||
741 | } | ||
742 | |||
743 | static void pt1_i2c_prepare(struct pt1 *pt1, int addr, int *addrp) | ||
744 | { | ||
745 | pt1_i2c_emit(pt1, addr, 1, 0, 1, 1, addr + 1); | ||
746 | pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2); | ||
747 | pt1_i2c_emit(pt1, addr + 2, 1, 0, 0, 0, addr + 3); | ||
748 | *addrp = addr + 3; | ||
749 | } | ||
750 | |||
751 | static void | ||
752 | pt1_i2c_write_msg(struct pt1 *pt1, int addr, int *addrp, struct i2c_msg *msg) | ||
753 | { | ||
754 | int i; | ||
755 | pt1_i2c_prepare(pt1, addr, &addr); | ||
756 | pt1_i2c_write_byte(pt1, addr, &addr, msg->addr << 1); | ||
757 | for (i = 0; i < msg->len; i++) | ||
758 | pt1_i2c_write_byte(pt1, addr, &addr, msg->buf[i]); | ||
759 | *addrp = addr; | ||
760 | } | ||
761 | |||
762 | static void | ||
763 | pt1_i2c_read_msg(struct pt1 *pt1, int addr, int *addrp, struct i2c_msg *msg) | ||
764 | { | ||
765 | int i; | ||
766 | pt1_i2c_prepare(pt1, addr, &addr); | ||
767 | pt1_i2c_write_byte(pt1, addr, &addr, msg->addr << 1 | 1); | ||
768 | for (i = 0; i < msg->len; i++) | ||
769 | pt1_i2c_read_byte(pt1, addr, &addr, i == msg->len - 1); | ||
770 | *addrp = addr; | ||
771 | } | ||
772 | |||
773 | static int pt1_i2c_end(struct pt1 *pt1, int addr) | ||
774 | { | ||
775 | pt1_i2c_emit(pt1, addr, 1, 0, 0, 0, addr + 1); | ||
776 | pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2); | ||
777 | pt1_i2c_emit(pt1, addr + 2, 1, 0, 1, 1, 0); | ||
778 | |||
779 | pt1_write_reg(pt1, 0, 0x00000004); | ||
780 | do { | ||
781 | if (signal_pending(current)) | ||
782 | return -EINTR; | ||
783 | schedule_timeout_interruptible((HZ + 999) / 1000); | ||
784 | } while (pt1_read_reg(pt1, 0) & 0x00000080); | ||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | static void pt1_i2c_begin(struct pt1 *pt1, int *addrp) | ||
789 | { | ||
790 | int addr; | ||
791 | addr = 0; | ||
792 | |||
793 | pt1_i2c_emit(pt1, addr, 0, 0, 1, 1, addr /* itself */); | ||
794 | addr = addr + 1; | ||
795 | |||
796 | if (!pt1->i2c_running) { | ||
797 | pt1_i2c_emit(pt1, addr, 1, 0, 1, 1, addr + 1); | ||
798 | pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2); | ||
799 | addr = addr + 2; | ||
800 | pt1->i2c_running = 1; | ||
801 | } | ||
802 | *addrp = addr; | ||
803 | } | ||
804 | |||
805 | static int pt1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | ||
806 | { | ||
807 | struct pt1 *pt1; | ||
808 | int i; | ||
809 | struct i2c_msg *msg, *next_msg; | ||
810 | int addr, ret; | ||
811 | u16 len; | ||
812 | u32 word; | ||
813 | |||
814 | pt1 = i2c_get_adapdata(adap); | ||
815 | |||
816 | for (i = 0; i < num; i++) { | ||
817 | msg = &msgs[i]; | ||
818 | if (msg->flags & I2C_M_RD) | ||
819 | return -ENOTSUPP; | ||
820 | |||
821 | if (i + 1 < num) | ||
822 | next_msg = &msgs[i + 1]; | ||
823 | else | ||
824 | next_msg = NULL; | ||
825 | |||
826 | if (next_msg && next_msg->flags & I2C_M_RD) { | ||
827 | i++; | ||
828 | |||
829 | len = next_msg->len; | ||
830 | if (len > 4) | ||
831 | return -ENOTSUPP; | ||
832 | |||
833 | pt1_i2c_begin(pt1, &addr); | ||
834 | pt1_i2c_write_msg(pt1, addr, &addr, msg); | ||
835 | pt1_i2c_read_msg(pt1, addr, &addr, next_msg); | ||
836 | ret = pt1_i2c_end(pt1, addr); | ||
837 | if (ret < 0) | ||
838 | return ret; | ||
839 | |||
840 | word = pt1_read_reg(pt1, 2); | ||
841 | while (len--) { | ||
842 | next_msg->buf[len] = word; | ||
843 | word >>= 8; | ||
844 | } | ||
845 | } else { | ||
846 | pt1_i2c_begin(pt1, &addr); | ||
847 | pt1_i2c_write_msg(pt1, addr, &addr, msg); | ||
848 | ret = pt1_i2c_end(pt1, addr); | ||
849 | if (ret < 0) | ||
850 | return ret; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | return num; | ||
855 | } | ||
856 | |||
857 | static u32 pt1_i2c_func(struct i2c_adapter *adap) | ||
858 | { | ||
859 | return I2C_FUNC_I2C; | ||
860 | } | ||
861 | |||
862 | static const struct i2c_algorithm pt1_i2c_algo = { | ||
863 | .master_xfer = pt1_i2c_xfer, | ||
864 | .functionality = pt1_i2c_func, | ||
865 | }; | ||
866 | |||
867 | static void pt1_i2c_wait(struct pt1 *pt1) | ||
868 | { | ||
869 | int i; | ||
870 | for (i = 0; i < 128; i++) | ||
871 | pt1_i2c_emit(pt1, 0, 0, 0, 1, 1, 0); | ||
872 | } | ||
873 | |||
874 | static void pt1_i2c_init(struct pt1 *pt1) | ||
875 | { | ||
876 | int i; | ||
877 | for (i = 0; i < 1024; i++) | ||
878 | pt1_i2c_emit(pt1, i, 0, 0, 1, 1, 0); | ||
879 | } | ||
880 | |||
881 | static void __devexit pt1_remove(struct pci_dev *pdev) | ||
882 | { | ||
883 | struct pt1 *pt1; | ||
884 | void __iomem *regs; | ||
885 | |||
886 | pt1 = pci_get_drvdata(pdev); | ||
887 | regs = pt1->regs; | ||
888 | |||
889 | kthread_stop(pt1->kthread); | ||
890 | pt1_cleanup_tables(pt1); | ||
891 | pt1_cleanup_adapters(pt1); | ||
892 | pt1_disable_ram(pt1); | ||
893 | pt1_set_power(pt1, 0, 0, 1); | ||
894 | i2c_del_adapter(&pt1->i2c_adap); | ||
895 | pci_set_drvdata(pdev, NULL); | ||
896 | kfree(pt1); | ||
897 | pci_iounmap(pdev, regs); | ||
898 | pci_release_regions(pdev); | ||
899 | pci_disable_device(pdev); | ||
900 | } | ||
901 | |||
902 | static int __devinit | ||
903 | pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
904 | { | ||
905 | int ret; | ||
906 | void __iomem *regs; | ||
907 | struct pt1 *pt1; | ||
908 | struct i2c_adapter *i2c_adap; | ||
909 | struct task_struct *kthread; | ||
910 | |||
911 | ret = pci_enable_device(pdev); | ||
912 | if (ret < 0) | ||
913 | goto err; | ||
914 | |||
915 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
916 | if (ret < 0) | ||
917 | goto err_pci_disable_device; | ||
918 | |||
919 | pci_set_master(pdev); | ||
920 | |||
921 | ret = pci_request_regions(pdev, DRIVER_NAME); | ||
922 | if (ret < 0) | ||
923 | goto err_pci_disable_device; | ||
924 | |||
925 | regs = pci_iomap(pdev, 0, 0); | ||
926 | if (!regs) { | ||
927 | ret = -EIO; | ||
928 | goto err_pci_release_regions; | ||
929 | } | ||
930 | |||
931 | pt1 = kzalloc(sizeof(struct pt1), GFP_KERNEL); | ||
932 | if (!pt1) { | ||
933 | ret = -ENOMEM; | ||
934 | goto err_pci_iounmap; | ||
935 | } | ||
936 | |||
937 | pt1->pdev = pdev; | ||
938 | pt1->regs = regs; | ||
939 | pci_set_drvdata(pdev, pt1); | ||
940 | |||
941 | i2c_adap = &pt1->i2c_adap; | ||
942 | i2c_adap->class = I2C_CLASS_TV_DIGITAL; | ||
943 | i2c_adap->algo = &pt1_i2c_algo; | ||
944 | i2c_adap->algo_data = NULL; | ||
945 | i2c_adap->dev.parent = &pdev->dev; | ||
946 | i2c_set_adapdata(i2c_adap, pt1); | ||
947 | ret = i2c_add_adapter(i2c_adap); | ||
948 | if (ret < 0) | ||
949 | goto err_kfree; | ||
950 | |||
951 | pt1_set_power(pt1, 0, 0, 1); | ||
952 | |||
953 | pt1_i2c_init(pt1); | ||
954 | pt1_i2c_wait(pt1); | ||
955 | |||
956 | ret = pt1_sync(pt1); | ||
957 | if (ret < 0) | ||
958 | goto err_i2c_del_adapter; | ||
959 | |||
960 | pt1_identify(pt1); | ||
961 | |||
962 | ret = pt1_unlock(pt1); | ||
963 | if (ret < 0) | ||
964 | goto err_i2c_del_adapter; | ||
965 | |||
966 | ret = pt1_reset_pci(pt1); | ||
967 | if (ret < 0) | ||
968 | goto err_i2c_del_adapter; | ||
969 | |||
970 | ret = pt1_reset_ram(pt1); | ||
971 | if (ret < 0) | ||
972 | goto err_i2c_del_adapter; | ||
973 | |||
974 | ret = pt1_enable_ram(pt1); | ||
975 | if (ret < 0) | ||
976 | goto err_i2c_del_adapter; | ||
977 | |||
978 | pt1_init_streams(pt1); | ||
979 | |||
980 | pt1_set_power(pt1, 1, 0, 1); | ||
981 | schedule_timeout_uninterruptible((HZ + 49) / 50); | ||
982 | |||
983 | pt1_set_power(pt1, 1, 0, 0); | ||
984 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
985 | |||
986 | ret = pt1_init_adapters(pt1); | ||
987 | if (ret < 0) | ||
988 | goto err_pt1_disable_ram; | ||
989 | |||
990 | ret = pt1_init_tables(pt1); | ||
991 | if (ret < 0) | ||
992 | goto err_pt1_cleanup_adapters; | ||
993 | |||
994 | kthread = kthread_run(pt1_thread, pt1, "pt1"); | ||
995 | if (IS_ERR(kthread)) { | ||
996 | ret = PTR_ERR(kthread); | ||
997 | goto err_pt1_cleanup_tables; | ||
998 | } | ||
999 | |||
1000 | pt1->kthread = kthread; | ||
1001 | return 0; | ||
1002 | |||
1003 | err_pt1_cleanup_tables: | ||
1004 | pt1_cleanup_tables(pt1); | ||
1005 | err_pt1_cleanup_adapters: | ||
1006 | pt1_cleanup_adapters(pt1); | ||
1007 | err_pt1_disable_ram: | ||
1008 | pt1_disable_ram(pt1); | ||
1009 | pt1_set_power(pt1, 0, 0, 1); | ||
1010 | err_i2c_del_adapter: | ||
1011 | i2c_del_adapter(i2c_adap); | ||
1012 | err_kfree: | ||
1013 | pci_set_drvdata(pdev, NULL); | ||
1014 | kfree(pt1); | ||
1015 | err_pci_iounmap: | ||
1016 | pci_iounmap(pdev, regs); | ||
1017 | err_pci_release_regions: | ||
1018 | pci_release_regions(pdev); | ||
1019 | err_pci_disable_device: | ||
1020 | pci_disable_device(pdev); | ||
1021 | err: | ||
1022 | return ret; | ||
1023 | |||
1024 | } | ||
1025 | |||
1026 | static struct pci_device_id pt1_id_table[] = { | ||
1027 | { PCI_DEVICE(0x10ee, 0x211a) }, | ||
1028 | { }, | ||
1029 | }; | ||
1030 | MODULE_DEVICE_TABLE(pci, pt1_id_table); | ||
1031 | |||
1032 | static struct pci_driver pt1_driver = { | ||
1033 | .name = DRIVER_NAME, | ||
1034 | .probe = pt1_probe, | ||
1035 | .remove = __devexit_p(pt1_remove), | ||
1036 | .id_table = pt1_id_table, | ||
1037 | }; | ||
1038 | |||
1039 | |||
1040 | static int __init pt1_init(void) | ||
1041 | { | ||
1042 | return pci_register_driver(&pt1_driver); | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | static void __exit pt1_cleanup(void) | ||
1047 | { | ||
1048 | pci_unregister_driver(&pt1_driver); | ||
1049 | } | ||
1050 | |||
1051 | module_init(pt1_init); | ||
1052 | module_exit(pt1_cleanup); | ||
1053 | |||
1054 | MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>"); | ||
1055 | MODULE_DESCRIPTION("Earthsoft PT1 Driver"); | ||
1056 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/dvb/pt1/va1j5jf8007s.c new file mode 100644 index 000000000000..2db940f8635f --- /dev/null +++ b/drivers/media/dvb/pt1/va1j5jf8007s.c | |||
@@ -0,0 +1,658 @@ | |||
1 | /* | ||
2 | * ISDB-S driver for VA1J5JF8007 | ||
3 | * | ||
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | ||
5 | * | ||
6 | * based on pt1dvr - http://pt1dvr.sourceforge.jp/ | ||
7 | * by Tomoaki Ishikawa <tomy@users.sourceforge.jp> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "va1j5jf8007s.h" | ||
30 | |||
31 | enum va1j5jf8007s_tune_state { | ||
32 | VA1J5JF8007S_IDLE, | ||
33 | VA1J5JF8007S_SET_FREQUENCY_1, | ||
34 | VA1J5JF8007S_SET_FREQUENCY_2, | ||
35 | VA1J5JF8007S_SET_FREQUENCY_3, | ||
36 | VA1J5JF8007S_CHECK_FREQUENCY, | ||
37 | VA1J5JF8007S_SET_MODULATION, | ||
38 | VA1J5JF8007S_CHECK_MODULATION, | ||
39 | VA1J5JF8007S_SET_TS_ID, | ||
40 | VA1J5JF8007S_CHECK_TS_ID, | ||
41 | VA1J5JF8007S_TRACK, | ||
42 | }; | ||
43 | |||
44 | struct va1j5jf8007s_state { | ||
45 | const struct va1j5jf8007s_config *config; | ||
46 | struct i2c_adapter *adap; | ||
47 | struct dvb_frontend fe; | ||
48 | enum va1j5jf8007s_tune_state tune_state; | ||
49 | }; | ||
50 | |||
51 | static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe) | ||
52 | { | ||
53 | return DVBFE_ALGO_HW; | ||
54 | } | ||
55 | |||
56 | static int | ||
57 | va1j5jf8007s_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
58 | { | ||
59 | struct va1j5jf8007s_state *state; | ||
60 | |||
61 | state = fe->demodulator_priv; | ||
62 | |||
63 | switch (state->tune_state) { | ||
64 | case VA1J5JF8007S_IDLE: | ||
65 | case VA1J5JF8007S_SET_FREQUENCY_1: | ||
66 | case VA1J5JF8007S_SET_FREQUENCY_2: | ||
67 | case VA1J5JF8007S_SET_FREQUENCY_3: | ||
68 | case VA1J5JF8007S_CHECK_FREQUENCY: | ||
69 | *status = 0; | ||
70 | return 0; | ||
71 | |||
72 | |||
73 | case VA1J5JF8007S_SET_MODULATION: | ||
74 | case VA1J5JF8007S_CHECK_MODULATION: | ||
75 | *status |= FE_HAS_SIGNAL; | ||
76 | return 0; | ||
77 | |||
78 | case VA1J5JF8007S_SET_TS_ID: | ||
79 | case VA1J5JF8007S_CHECK_TS_ID: | ||
80 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
81 | return 0; | ||
82 | |||
83 | case VA1J5JF8007S_TRACK: | ||
84 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | BUG(); | ||
89 | } | ||
90 | |||
91 | struct va1j5jf8007s_cb_map { | ||
92 | u32 frequency; | ||
93 | u8 cb; | ||
94 | }; | ||
95 | |||
96 | static const struct va1j5jf8007s_cb_map va1j5jf8007s_cb_maps[] = { | ||
97 | { 986000, 0xb2 }, | ||
98 | { 1072000, 0xd2 }, | ||
99 | { 1154000, 0xe2 }, | ||
100 | { 1291000, 0x20 }, | ||
101 | { 1447000, 0x40 }, | ||
102 | { 1615000, 0x60 }, | ||
103 | { 1791000, 0x80 }, | ||
104 | { 1972000, 0xa0 }, | ||
105 | }; | ||
106 | |||
107 | static u8 va1j5jf8007s_lookup_cb(u32 frequency) | ||
108 | { | ||
109 | int i; | ||
110 | const struct va1j5jf8007s_cb_map *map; | ||
111 | |||
112 | for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_cb_maps); i++) { | ||
113 | map = &va1j5jf8007s_cb_maps[i]; | ||
114 | if (frequency < map->frequency) | ||
115 | return map->cb; | ||
116 | } | ||
117 | return 0xc0; | ||
118 | } | ||
119 | |||
120 | static int va1j5jf8007s_set_frequency_1(struct va1j5jf8007s_state *state) | ||
121 | { | ||
122 | u32 frequency; | ||
123 | u16 word; | ||
124 | u8 buf[6]; | ||
125 | struct i2c_msg msg; | ||
126 | |||
127 | frequency = state->fe.dtv_property_cache.frequency; | ||
128 | |||
129 | word = (frequency + 500) / 1000; | ||
130 | if (frequency < 1072000) | ||
131 | word = (word << 1 & ~0x1f) | (word & 0x0f); | ||
132 | |||
133 | buf[0] = 0xfe; | ||
134 | buf[1] = 0xc0; | ||
135 | buf[2] = 0x40 | word >> 8; | ||
136 | buf[3] = word; | ||
137 | buf[4] = 0xe0; | ||
138 | buf[5] = va1j5jf8007s_lookup_cb(frequency); | ||
139 | |||
140 | msg.addr = state->config->demod_address; | ||
141 | msg.flags = 0; | ||
142 | msg.len = sizeof(buf); | ||
143 | msg.buf = buf; | ||
144 | |||
145 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
146 | return -EREMOTEIO; | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int va1j5jf8007s_set_frequency_2(struct va1j5jf8007s_state *state) | ||
152 | { | ||
153 | u8 buf[3]; | ||
154 | struct i2c_msg msg; | ||
155 | |||
156 | buf[0] = 0xfe; | ||
157 | buf[1] = 0xc0; | ||
158 | buf[2] = 0xe4; | ||
159 | |||
160 | msg.addr = state->config->demod_address; | ||
161 | msg.flags = 0; | ||
162 | msg.len = sizeof(buf); | ||
163 | msg.buf = buf; | ||
164 | |||
165 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
166 | return -EREMOTEIO; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int va1j5jf8007s_set_frequency_3(struct va1j5jf8007s_state *state) | ||
172 | { | ||
173 | u32 frequency; | ||
174 | u8 buf[4]; | ||
175 | struct i2c_msg msg; | ||
176 | |||
177 | frequency = state->fe.dtv_property_cache.frequency; | ||
178 | |||
179 | buf[0] = 0xfe; | ||
180 | buf[1] = 0xc0; | ||
181 | buf[2] = 0xf4; | ||
182 | buf[3] = va1j5jf8007s_lookup_cb(frequency) | 0x4; | ||
183 | |||
184 | msg.addr = state->config->demod_address; | ||
185 | msg.flags = 0; | ||
186 | msg.len = sizeof(buf); | ||
187 | msg.buf = buf; | ||
188 | |||
189 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
190 | return -EREMOTEIO; | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | va1j5jf8007s_check_frequency(struct va1j5jf8007s_state *state, int *lock) | ||
197 | { | ||
198 | u8 addr; | ||
199 | u8 write_buf[2], read_buf[1]; | ||
200 | struct i2c_msg msgs[2]; | ||
201 | |||
202 | addr = state->config->demod_address; | ||
203 | |||
204 | write_buf[0] = 0xfe; | ||
205 | write_buf[1] = 0xc1; | ||
206 | |||
207 | msgs[0].addr = addr; | ||
208 | msgs[0].flags = 0; | ||
209 | msgs[0].len = sizeof(write_buf); | ||
210 | msgs[0].buf = write_buf; | ||
211 | |||
212 | msgs[1].addr = addr; | ||
213 | msgs[1].flags = I2C_M_RD; | ||
214 | msgs[1].len = sizeof(read_buf); | ||
215 | msgs[1].buf = read_buf; | ||
216 | |||
217 | if (i2c_transfer(state->adap, msgs, 2) != 2) | ||
218 | return -EREMOTEIO; | ||
219 | |||
220 | *lock = read_buf[0] & 0x40; | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int va1j5jf8007s_set_modulation(struct va1j5jf8007s_state *state) | ||
225 | { | ||
226 | u8 buf[2]; | ||
227 | struct i2c_msg msg; | ||
228 | |||
229 | buf[0] = 0x03; | ||
230 | buf[1] = 0x01; | ||
231 | |||
232 | msg.addr = state->config->demod_address; | ||
233 | msg.flags = 0; | ||
234 | msg.len = sizeof(buf); | ||
235 | msg.buf = buf; | ||
236 | |||
237 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
238 | return -EREMOTEIO; | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int | ||
244 | va1j5jf8007s_check_modulation(struct va1j5jf8007s_state *state, int *lock) | ||
245 | { | ||
246 | u8 addr; | ||
247 | u8 write_buf[1], read_buf[1]; | ||
248 | struct i2c_msg msgs[2]; | ||
249 | |||
250 | addr = state->config->demod_address; | ||
251 | |||
252 | write_buf[0] = 0xc3; | ||
253 | |||
254 | msgs[0].addr = addr; | ||
255 | msgs[0].flags = 0; | ||
256 | msgs[0].len = sizeof(write_buf); | ||
257 | msgs[0].buf = write_buf; | ||
258 | |||
259 | msgs[1].addr = addr; | ||
260 | msgs[1].flags = I2C_M_RD; | ||
261 | msgs[1].len = sizeof(read_buf); | ||
262 | msgs[1].buf = read_buf; | ||
263 | |||
264 | if (i2c_transfer(state->adap, msgs, 2) != 2) | ||
265 | return -EREMOTEIO; | ||
266 | |||
267 | *lock = !(read_buf[0] & 0x10); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int | ||
272 | va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state) | ||
273 | { | ||
274 | u32 ts_id; | ||
275 | u8 buf[3]; | ||
276 | struct i2c_msg msg; | ||
277 | |||
278 | ts_id = state->fe.dtv_property_cache.isdbs_ts_id; | ||
279 | if (!ts_id) | ||
280 | return 0; | ||
281 | |||
282 | buf[0] = 0x8f; | ||
283 | buf[1] = ts_id >> 8; | ||
284 | buf[2] = ts_id; | ||
285 | |||
286 | msg.addr = state->config->demod_address; | ||
287 | msg.flags = 0; | ||
288 | msg.len = sizeof(buf); | ||
289 | msg.buf = buf; | ||
290 | |||
291 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
292 | return -EREMOTEIO; | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int | ||
298 | va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock) | ||
299 | { | ||
300 | u8 addr; | ||
301 | u8 write_buf[1], read_buf[2]; | ||
302 | struct i2c_msg msgs[2]; | ||
303 | u32 ts_id; | ||
304 | |||
305 | ts_id = state->fe.dtv_property_cache.isdbs_ts_id; | ||
306 | if (!ts_id) { | ||
307 | *lock = 1; | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | addr = state->config->demod_address; | ||
312 | |||
313 | write_buf[0] = 0xe6; | ||
314 | |||
315 | msgs[0].addr = addr; | ||
316 | msgs[0].flags = 0; | ||
317 | msgs[0].len = sizeof(write_buf); | ||
318 | msgs[0].buf = write_buf; | ||
319 | |||
320 | msgs[1].addr = addr; | ||
321 | msgs[1].flags = I2C_M_RD; | ||
322 | msgs[1].len = sizeof(read_buf); | ||
323 | msgs[1].buf = read_buf; | ||
324 | |||
325 | if (i2c_transfer(state->adap, msgs, 2) != 2) | ||
326 | return -EREMOTEIO; | ||
327 | |||
328 | *lock = (read_buf[0] << 8 | read_buf[1]) == ts_id; | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int | ||
333 | va1j5jf8007s_tune(struct dvb_frontend *fe, | ||
334 | struct dvb_frontend_parameters *params, | ||
335 | unsigned int mode_flags, unsigned int *delay, | ||
336 | fe_status_t *status) | ||
337 | { | ||
338 | struct va1j5jf8007s_state *state; | ||
339 | int ret; | ||
340 | int lock; | ||
341 | |||
342 | state = fe->demodulator_priv; | ||
343 | |||
344 | if (params != NULL) | ||
345 | state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1; | ||
346 | |||
347 | switch (state->tune_state) { | ||
348 | case VA1J5JF8007S_IDLE: | ||
349 | *delay = 3 * HZ; | ||
350 | *status = 0; | ||
351 | return 0; | ||
352 | |||
353 | case VA1J5JF8007S_SET_FREQUENCY_1: | ||
354 | ret = va1j5jf8007s_set_frequency_1(state); | ||
355 | if (ret < 0) | ||
356 | return ret; | ||
357 | |||
358 | state->tune_state = VA1J5JF8007S_SET_FREQUENCY_2; | ||
359 | *delay = 0; | ||
360 | *status = 0; | ||
361 | return 0; | ||
362 | |||
363 | case VA1J5JF8007S_SET_FREQUENCY_2: | ||
364 | ret = va1j5jf8007s_set_frequency_2(state); | ||
365 | if (ret < 0) | ||
366 | return ret; | ||
367 | |||
368 | state->tune_state = VA1J5JF8007S_SET_FREQUENCY_3; | ||
369 | *delay = (HZ + 99) / 100; | ||
370 | *status = 0; | ||
371 | return 0; | ||
372 | |||
373 | case VA1J5JF8007S_SET_FREQUENCY_3: | ||
374 | ret = va1j5jf8007s_set_frequency_3(state); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | |||
378 | state->tune_state = VA1J5JF8007S_CHECK_FREQUENCY; | ||
379 | *delay = 0; | ||
380 | *status = 0; | ||
381 | return 0; | ||
382 | |||
383 | case VA1J5JF8007S_CHECK_FREQUENCY: | ||
384 | ret = va1j5jf8007s_check_frequency(state, &lock); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | if (!lock) { | ||
389 | *delay = (HZ + 999) / 1000; | ||
390 | *status = 0; | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | state->tune_state = VA1J5JF8007S_SET_MODULATION; | ||
395 | *delay = 0; | ||
396 | *status = FE_HAS_SIGNAL; | ||
397 | return 0; | ||
398 | |||
399 | case VA1J5JF8007S_SET_MODULATION: | ||
400 | ret = va1j5jf8007s_set_modulation(state); | ||
401 | if (ret < 0) | ||
402 | return ret; | ||
403 | |||
404 | state->tune_state = VA1J5JF8007S_CHECK_MODULATION; | ||
405 | *delay = 0; | ||
406 | *status = FE_HAS_SIGNAL; | ||
407 | return 0; | ||
408 | |||
409 | case VA1J5JF8007S_CHECK_MODULATION: | ||
410 | ret = va1j5jf8007s_check_modulation(state, &lock); | ||
411 | if (ret < 0) | ||
412 | return ret; | ||
413 | |||
414 | if (!lock) { | ||
415 | *delay = (HZ + 49) / 50; | ||
416 | *status = FE_HAS_SIGNAL; | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | state->tune_state = VA1J5JF8007S_SET_TS_ID; | ||
421 | *delay = 0; | ||
422 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
423 | return 0; | ||
424 | |||
425 | case VA1J5JF8007S_SET_TS_ID: | ||
426 | ret = va1j5jf8007s_set_ts_id(state); | ||
427 | if (ret < 0) | ||
428 | return ret; | ||
429 | |||
430 | state->tune_state = VA1J5JF8007S_CHECK_TS_ID; | ||
431 | return 0; | ||
432 | |||
433 | case VA1J5JF8007S_CHECK_TS_ID: | ||
434 | ret = va1j5jf8007s_check_ts_id(state, &lock); | ||
435 | if (ret < 0) | ||
436 | return ret; | ||
437 | |||
438 | if (!lock) { | ||
439 | *delay = (HZ + 99) / 100; | ||
440 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | state->tune_state = VA1J5JF8007S_TRACK; | ||
445 | /* fall through */ | ||
446 | |||
447 | case VA1J5JF8007S_TRACK: | ||
448 | *delay = 3 * HZ; | ||
449 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | BUG(); | ||
454 | } | ||
455 | |||
456 | static int va1j5jf8007s_init_frequency(struct va1j5jf8007s_state *state) | ||
457 | { | ||
458 | u8 buf[4]; | ||
459 | struct i2c_msg msg; | ||
460 | |||
461 | buf[0] = 0xfe; | ||
462 | buf[1] = 0xc0; | ||
463 | buf[2] = 0xf0; | ||
464 | buf[3] = 0x04; | ||
465 | |||
466 | msg.addr = state->config->demod_address; | ||
467 | msg.flags = 0; | ||
468 | msg.len = sizeof(buf); | ||
469 | msg.buf = buf; | ||
470 | |||
471 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
472 | return -EREMOTEIO; | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int va1j5jf8007s_set_sleep(struct va1j5jf8007s_state *state, int sleep) | ||
478 | { | ||
479 | u8 buf[2]; | ||
480 | struct i2c_msg msg; | ||
481 | |||
482 | buf[0] = 0x17; | ||
483 | buf[1] = sleep ? 0x01 : 0x00; | ||
484 | |||
485 | msg.addr = state->config->demod_address; | ||
486 | msg.flags = 0; | ||
487 | msg.len = sizeof(buf); | ||
488 | msg.buf = buf; | ||
489 | |||
490 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
491 | return -EREMOTEIO; | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int va1j5jf8007s_sleep(struct dvb_frontend *fe) | ||
497 | { | ||
498 | struct va1j5jf8007s_state *state; | ||
499 | int ret; | ||
500 | |||
501 | state = fe->demodulator_priv; | ||
502 | |||
503 | ret = va1j5jf8007s_init_frequency(state); | ||
504 | if (ret < 0) | ||
505 | return ret; | ||
506 | |||
507 | return va1j5jf8007s_set_sleep(state, 1); | ||
508 | } | ||
509 | |||
510 | static int va1j5jf8007s_init(struct dvb_frontend *fe) | ||
511 | { | ||
512 | struct va1j5jf8007s_state *state; | ||
513 | |||
514 | state = fe->demodulator_priv; | ||
515 | state->tune_state = VA1J5JF8007S_IDLE; | ||
516 | |||
517 | return va1j5jf8007s_set_sleep(state, 0); | ||
518 | } | ||
519 | |||
520 | static void va1j5jf8007s_release(struct dvb_frontend *fe) | ||
521 | { | ||
522 | struct va1j5jf8007s_state *state; | ||
523 | state = fe->demodulator_priv; | ||
524 | kfree(state); | ||
525 | } | ||
526 | |||
527 | static struct dvb_frontend_ops va1j5jf8007s_ops = { | ||
528 | .info = { | ||
529 | .name = "VA1J5JF8007 ISDB-S", | ||
530 | .type = FE_QPSK, | ||
531 | .frequency_min = 950000, | ||
532 | .frequency_max = 2150000, | ||
533 | .frequency_stepsize = 1000, | ||
534 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | | ||
535 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
536 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, | ||
537 | }, | ||
538 | |||
539 | .get_frontend_algo = va1j5jf8007s_get_frontend_algo, | ||
540 | .read_status = va1j5jf8007s_read_status, | ||
541 | .tune = va1j5jf8007s_tune, | ||
542 | .sleep = va1j5jf8007s_sleep, | ||
543 | .init = va1j5jf8007s_init, | ||
544 | .release = va1j5jf8007s_release, | ||
545 | }; | ||
546 | |||
547 | static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state) | ||
548 | { | ||
549 | u8 addr; | ||
550 | u8 write_buf[1], read_buf[1]; | ||
551 | struct i2c_msg msgs[2]; | ||
552 | |||
553 | addr = state->config->demod_address; | ||
554 | |||
555 | write_buf[0] = 0x07; | ||
556 | |||
557 | msgs[0].addr = addr; | ||
558 | msgs[0].flags = 0; | ||
559 | msgs[0].len = sizeof(write_buf); | ||
560 | msgs[0].buf = write_buf; | ||
561 | |||
562 | msgs[1].addr = addr; | ||
563 | msgs[1].flags = I2C_M_RD; | ||
564 | msgs[1].len = sizeof(read_buf); | ||
565 | msgs[1].buf = read_buf; | ||
566 | |||
567 | if (i2c_transfer(state->adap, msgs, 2) != 2) | ||
568 | return -EREMOTEIO; | ||
569 | |||
570 | if (read_buf[0] != 0x41) | ||
571 | return -EIO; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static const u8 va1j5jf8007s_prepare_bufs[][2] = { | ||
577 | {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, | ||
578 | {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, | ||
579 | {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, | ||
580 | {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0}, | ||
581 | }; | ||
582 | |||
583 | static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state) | ||
584 | { | ||
585 | u8 addr; | ||
586 | u8 buf[2]; | ||
587 | struct i2c_msg msg; | ||
588 | int i; | ||
589 | |||
590 | addr = state->config->demod_address; | ||
591 | |||
592 | msg.addr = addr; | ||
593 | msg.flags = 0; | ||
594 | msg.len = 2; | ||
595 | msg.buf = buf; | ||
596 | for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_prepare_bufs); i++) { | ||
597 | memcpy(buf, va1j5jf8007s_prepare_bufs[i], sizeof(buf)); | ||
598 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
599 | return -EREMOTEIO; | ||
600 | } | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | /* must be called after va1j5jf8007t_attach */ | ||
606 | int va1j5jf8007s_prepare(struct dvb_frontend *fe) | ||
607 | { | ||
608 | struct va1j5jf8007s_state *state; | ||
609 | int ret; | ||
610 | |||
611 | state = fe->demodulator_priv; | ||
612 | |||
613 | ret = va1j5jf8007s_prepare_1(state); | ||
614 | if (ret < 0) | ||
615 | return ret; | ||
616 | |||
617 | ret = va1j5jf8007s_prepare_2(state); | ||
618 | if (ret < 0) | ||
619 | return ret; | ||
620 | |||
621 | return va1j5jf8007s_init_frequency(state); | ||
622 | } | ||
623 | |||
624 | struct dvb_frontend * | ||
625 | va1j5jf8007s_attach(const struct va1j5jf8007s_config *config, | ||
626 | struct i2c_adapter *adap) | ||
627 | { | ||
628 | struct va1j5jf8007s_state *state; | ||
629 | struct dvb_frontend *fe; | ||
630 | u8 buf[2]; | ||
631 | struct i2c_msg msg; | ||
632 | |||
633 | state = kzalloc(sizeof(struct va1j5jf8007s_state), GFP_KERNEL); | ||
634 | if (!state) | ||
635 | return NULL; | ||
636 | |||
637 | state->config = config; | ||
638 | state->adap = adap; | ||
639 | |||
640 | fe = &state->fe; | ||
641 | memcpy(&fe->ops, &va1j5jf8007s_ops, sizeof(struct dvb_frontend_ops)); | ||
642 | fe->demodulator_priv = state; | ||
643 | |||
644 | buf[0] = 0x01; | ||
645 | buf[1] = 0x80; | ||
646 | |||
647 | msg.addr = state->config->demod_address; | ||
648 | msg.flags = 0; | ||
649 | msg.len = sizeof(buf); | ||
650 | msg.buf = buf; | ||
651 | |||
652 | if (i2c_transfer(state->adap, &msg, 1) != 1) { | ||
653 | kfree(state); | ||
654 | return NULL; | ||
655 | } | ||
656 | |||
657 | return fe; | ||
658 | } | ||
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.h b/drivers/media/dvb/pt1/va1j5jf8007s.h new file mode 100644 index 000000000000..aa228a816353 --- /dev/null +++ b/drivers/media/dvb/pt1/va1j5jf8007s.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * ISDB-S driver for VA1J5JF8007 | ||
3 | * | ||
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | ||
5 | * | ||
6 | * based on pt1dvr - http://pt1dvr.sourceforge.jp/ | ||
7 | * by Tomoaki Ishikawa <tomy@users.sourceforge.jp> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef VA1J5JF8007S_H | ||
25 | #define VA1J5JF8007S_H | ||
26 | |||
27 | struct va1j5jf8007s_config { | ||
28 | u8 demod_address; | ||
29 | }; | ||
30 | |||
31 | struct i2c_adapter; | ||
32 | |||
33 | struct dvb_frontend * | ||
34 | va1j5jf8007s_attach(const struct va1j5jf8007s_config *config, | ||
35 | struct i2c_adapter *adap); | ||
36 | |||
37 | /* must be called after va1j5jf8007t_attach */ | ||
38 | int va1j5jf8007s_prepare(struct dvb_frontend *fe); | ||
39 | |||
40 | #endif | ||
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/dvb/pt1/va1j5jf8007t.c new file mode 100644 index 000000000000..71117f4ca7e6 --- /dev/null +++ b/drivers/media/dvb/pt1/va1j5jf8007t.c | |||
@@ -0,0 +1,468 @@ | |||
1 | /* | ||
2 | * ISDB-T driver for VA1J5JF8007 | ||
3 | * | ||
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | ||
5 | * | ||
6 | * based on pt1dvr - http://pt1dvr.sourceforge.jp/ | ||
7 | * by Tomoaki Ishikawa <tomy@users.sourceforge.jp> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_math.h" | ||
30 | #include "va1j5jf8007t.h" | ||
31 | |||
32 | enum va1j5jf8007t_tune_state { | ||
33 | VA1J5JF8007T_IDLE, | ||
34 | VA1J5JF8007T_SET_FREQUENCY, | ||
35 | VA1J5JF8007T_CHECK_FREQUENCY, | ||
36 | VA1J5JF8007T_SET_MODULATION, | ||
37 | VA1J5JF8007T_CHECK_MODULATION, | ||
38 | VA1J5JF8007T_TRACK, | ||
39 | VA1J5JF8007T_ABORT, | ||
40 | }; | ||
41 | |||
42 | struct va1j5jf8007t_state { | ||
43 | const struct va1j5jf8007t_config *config; | ||
44 | struct i2c_adapter *adap; | ||
45 | struct dvb_frontend fe; | ||
46 | enum va1j5jf8007t_tune_state tune_state; | ||
47 | }; | ||
48 | |||
49 | static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe) | ||
50 | { | ||
51 | return DVBFE_ALGO_HW; | ||
52 | } | ||
53 | |||
54 | static int | ||
55 | va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
56 | { | ||
57 | struct va1j5jf8007t_state *state; | ||
58 | |||
59 | state = fe->demodulator_priv; | ||
60 | |||
61 | switch (state->tune_state) { | ||
62 | case VA1J5JF8007T_IDLE: | ||
63 | case VA1J5JF8007T_SET_FREQUENCY: | ||
64 | case VA1J5JF8007T_CHECK_FREQUENCY: | ||
65 | *status = 0; | ||
66 | return 0; | ||
67 | |||
68 | |||
69 | case VA1J5JF8007T_SET_MODULATION: | ||
70 | case VA1J5JF8007T_CHECK_MODULATION: | ||
71 | case VA1J5JF8007T_ABORT: | ||
72 | *status |= FE_HAS_SIGNAL; | ||
73 | return 0; | ||
74 | |||
75 | case VA1J5JF8007T_TRACK: | ||
76 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | BUG(); | ||
81 | } | ||
82 | |||
83 | struct va1j5jf8007t_cb_map { | ||
84 | u32 frequency; | ||
85 | u8 cb; | ||
86 | }; | ||
87 | |||
88 | static const struct va1j5jf8007t_cb_map va1j5jf8007t_cb_maps[] = { | ||
89 | { 90000000, 0x80 }, | ||
90 | { 140000000, 0x81 }, | ||
91 | { 170000000, 0xa1 }, | ||
92 | { 220000000, 0x62 }, | ||
93 | { 330000000, 0xa2 }, | ||
94 | { 402000000, 0xe2 }, | ||
95 | { 450000000, 0x64 }, | ||
96 | { 550000000, 0x84 }, | ||
97 | { 600000000, 0xa4 }, | ||
98 | { 700000000, 0xc4 }, | ||
99 | }; | ||
100 | |||
101 | static u8 va1j5jf8007t_lookup_cb(u32 frequency) | ||
102 | { | ||
103 | int i; | ||
104 | const struct va1j5jf8007t_cb_map *map; | ||
105 | |||
106 | for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_cb_maps); i++) { | ||
107 | map = &va1j5jf8007t_cb_maps[i]; | ||
108 | if (frequency < map->frequency) | ||
109 | return map->cb; | ||
110 | } | ||
111 | return 0xe4; | ||
112 | } | ||
113 | |||
114 | static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state) | ||
115 | { | ||
116 | u32 frequency; | ||
117 | u16 word; | ||
118 | u8 buf[6]; | ||
119 | struct i2c_msg msg; | ||
120 | |||
121 | frequency = state->fe.dtv_property_cache.frequency; | ||
122 | |||
123 | word = (frequency + 71428) / 142857 + 399; | ||
124 | buf[0] = 0xfe; | ||
125 | buf[1] = 0xc2; | ||
126 | buf[2] = word >> 8; | ||
127 | buf[3] = word; | ||
128 | buf[4] = 0x80; | ||
129 | buf[5] = va1j5jf8007t_lookup_cb(frequency); | ||
130 | |||
131 | msg.addr = state->config->demod_address; | ||
132 | msg.flags = 0; | ||
133 | msg.len = sizeof(buf); | ||
134 | msg.buf = buf; | ||
135 | |||
136 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
137 | return -EREMOTEIO; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int | ||
143 | va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock) | ||
144 | { | ||
145 | u8 addr; | ||
146 | u8 write_buf[2], read_buf[1]; | ||
147 | struct i2c_msg msgs[2]; | ||
148 | |||
149 | addr = state->config->demod_address; | ||
150 | |||
151 | write_buf[0] = 0xfe; | ||
152 | write_buf[1] = 0xc3; | ||
153 | |||
154 | msgs[0].addr = addr; | ||
155 | msgs[0].flags = 0; | ||
156 | msgs[0].len = sizeof(write_buf); | ||
157 | msgs[0].buf = write_buf; | ||
158 | |||
159 | msgs[1].addr = addr; | ||
160 | msgs[1].flags = I2C_M_RD; | ||
161 | msgs[1].len = sizeof(read_buf); | ||
162 | msgs[1].buf = read_buf; | ||
163 | |||
164 | if (i2c_transfer(state->adap, msgs, 2) != 2) | ||
165 | return -EREMOTEIO; | ||
166 | |||
167 | *lock = read_buf[0] & 0x40; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state) | ||
172 | { | ||
173 | u8 buf[2]; | ||
174 | struct i2c_msg msg; | ||
175 | |||
176 | buf[0] = 0x01; | ||
177 | buf[1] = 0x40; | ||
178 | |||
179 | msg.addr = state->config->demod_address; | ||
180 | msg.flags = 0; | ||
181 | msg.len = sizeof(buf); | ||
182 | msg.buf = buf; | ||
183 | |||
184 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
185 | return -EREMOTEIO; | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state, | ||
191 | int *lock, int *retry) | ||
192 | { | ||
193 | u8 addr; | ||
194 | u8 write_buf[1], read_buf[1]; | ||
195 | struct i2c_msg msgs[2]; | ||
196 | |||
197 | addr = state->config->demod_address; | ||
198 | |||
199 | write_buf[0] = 0x80; | ||
200 | |||
201 | msgs[0].addr = addr; | ||
202 | msgs[0].flags = 0; | ||
203 | msgs[0].len = sizeof(write_buf); | ||
204 | msgs[0].buf = write_buf; | ||
205 | |||
206 | msgs[1].addr = addr; | ||
207 | msgs[1].flags = I2C_M_RD; | ||
208 | msgs[1].len = sizeof(read_buf); | ||
209 | msgs[1].buf = read_buf; | ||
210 | |||
211 | if (i2c_transfer(state->adap, msgs, 2) != 2) | ||
212 | return -EREMOTEIO; | ||
213 | |||
214 | *lock = !(read_buf[0] & 0x10); | ||
215 | *retry = read_buf[0] & 0x80; | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int | ||
220 | va1j5jf8007t_tune(struct dvb_frontend *fe, | ||
221 | struct dvb_frontend_parameters *params, | ||
222 | unsigned int mode_flags, unsigned int *delay, | ||
223 | fe_status_t *status) | ||
224 | { | ||
225 | struct va1j5jf8007t_state *state; | ||
226 | int ret; | ||
227 | int lock, retry; | ||
228 | |||
229 | state = fe->demodulator_priv; | ||
230 | |||
231 | if (params != NULL) | ||
232 | state->tune_state = VA1J5JF8007T_SET_FREQUENCY; | ||
233 | |||
234 | switch (state->tune_state) { | ||
235 | case VA1J5JF8007T_IDLE: | ||
236 | *delay = 3 * HZ; | ||
237 | *status = 0; | ||
238 | return 0; | ||
239 | |||
240 | case VA1J5JF8007T_SET_FREQUENCY: | ||
241 | ret = va1j5jf8007t_set_frequency(state); | ||
242 | if (ret < 0) | ||
243 | return ret; | ||
244 | |||
245 | state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY; | ||
246 | *delay = 0; | ||
247 | *status = 0; | ||
248 | return 0; | ||
249 | |||
250 | case VA1J5JF8007T_CHECK_FREQUENCY: | ||
251 | ret = va1j5jf8007t_check_frequency(state, &lock); | ||
252 | if (ret < 0) | ||
253 | return ret; | ||
254 | |||
255 | if (!lock) { | ||
256 | *delay = (HZ + 999) / 1000; | ||
257 | *status = 0; | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | state->tune_state = VA1J5JF8007T_SET_MODULATION; | ||
262 | *delay = 0; | ||
263 | *status = FE_HAS_SIGNAL; | ||
264 | return 0; | ||
265 | |||
266 | case VA1J5JF8007T_SET_MODULATION: | ||
267 | ret = va1j5jf8007t_set_modulation(state); | ||
268 | if (ret < 0) | ||
269 | return ret; | ||
270 | |||
271 | state->tune_state = VA1J5JF8007T_CHECK_MODULATION; | ||
272 | *delay = 0; | ||
273 | *status = FE_HAS_SIGNAL; | ||
274 | return 0; | ||
275 | |||
276 | case VA1J5JF8007T_CHECK_MODULATION: | ||
277 | ret = va1j5jf8007t_check_modulation(state, &lock, &retry); | ||
278 | if (ret < 0) | ||
279 | return ret; | ||
280 | |||
281 | if (!lock) { | ||
282 | if (!retry) { | ||
283 | state->tune_state = VA1J5JF8007T_ABORT; | ||
284 | *delay = 3 * HZ; | ||
285 | *status = FE_HAS_SIGNAL; | ||
286 | return 0; | ||
287 | } | ||
288 | *delay = (HZ + 999) / 1000; | ||
289 | *status = FE_HAS_SIGNAL; | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | state->tune_state = VA1J5JF8007T_TRACK; | ||
294 | /* fall through */ | ||
295 | |||
296 | case VA1J5JF8007T_TRACK: | ||
297 | *delay = 3 * HZ; | ||
298 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
299 | return 0; | ||
300 | |||
301 | case VA1J5JF8007T_ABORT: | ||
302 | *delay = 3 * HZ; | ||
303 | *status = FE_HAS_SIGNAL; | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | BUG(); | ||
308 | } | ||
309 | |||
310 | static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state) | ||
311 | { | ||
312 | u8 buf[7]; | ||
313 | struct i2c_msg msg; | ||
314 | |||
315 | buf[0] = 0xfe; | ||
316 | buf[1] = 0xc2; | ||
317 | buf[2] = 0x01; | ||
318 | buf[3] = 0x8f; | ||
319 | buf[4] = 0xc1; | ||
320 | buf[5] = 0x80; | ||
321 | buf[6] = 0x80; | ||
322 | |||
323 | msg.addr = state->config->demod_address; | ||
324 | msg.flags = 0; | ||
325 | msg.len = sizeof(buf); | ||
326 | msg.buf = buf; | ||
327 | |||
328 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
329 | return -EREMOTEIO; | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep) | ||
335 | { | ||
336 | u8 buf[2]; | ||
337 | struct i2c_msg msg; | ||
338 | |||
339 | buf[0] = 0x03; | ||
340 | buf[1] = sleep ? 0x90 : 0x80; | ||
341 | |||
342 | msg.addr = state->config->demod_address; | ||
343 | msg.flags = 0; | ||
344 | msg.len = sizeof(buf); | ||
345 | msg.buf = buf; | ||
346 | |||
347 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
348 | return -EREMOTEIO; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int va1j5jf8007t_sleep(struct dvb_frontend *fe) | ||
354 | { | ||
355 | struct va1j5jf8007t_state *state; | ||
356 | int ret; | ||
357 | |||
358 | state = fe->demodulator_priv; | ||
359 | |||
360 | ret = va1j5jf8007t_init_frequency(state); | ||
361 | if (ret < 0) | ||
362 | return ret; | ||
363 | |||
364 | return va1j5jf8007t_set_sleep(state, 1); | ||
365 | } | ||
366 | |||
367 | static int va1j5jf8007t_init(struct dvb_frontend *fe) | ||
368 | { | ||
369 | struct va1j5jf8007t_state *state; | ||
370 | |||
371 | state = fe->demodulator_priv; | ||
372 | state->tune_state = VA1J5JF8007T_IDLE; | ||
373 | |||
374 | return va1j5jf8007t_set_sleep(state, 0); | ||
375 | } | ||
376 | |||
377 | static void va1j5jf8007t_release(struct dvb_frontend *fe) | ||
378 | { | ||
379 | struct va1j5jf8007t_state *state; | ||
380 | state = fe->demodulator_priv; | ||
381 | kfree(state); | ||
382 | } | ||
383 | |||
384 | static struct dvb_frontend_ops va1j5jf8007t_ops = { | ||
385 | .info = { | ||
386 | .name = "VA1J5JF8007 ISDB-T", | ||
387 | .type = FE_OFDM, | ||
388 | .frequency_min = 90000000, | ||
389 | .frequency_max = 770000000, | ||
390 | .frequency_stepsize = 142857, | ||
391 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | | ||
392 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
393 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, | ||
394 | }, | ||
395 | |||
396 | .get_frontend_algo = va1j5jf8007t_get_frontend_algo, | ||
397 | .read_status = va1j5jf8007t_read_status, | ||
398 | .tune = va1j5jf8007t_tune, | ||
399 | .sleep = va1j5jf8007t_sleep, | ||
400 | .init = va1j5jf8007t_init, | ||
401 | .release = va1j5jf8007t_release, | ||
402 | }; | ||
403 | |||
404 | static const u8 va1j5jf8007t_prepare_bufs[][2] = { | ||
405 | {0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, | ||
406 | {0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00}, | ||
407 | {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03}, | ||
408 | {0xef, 0x01} | ||
409 | }; | ||
410 | |||
411 | int va1j5jf8007t_prepare(struct dvb_frontend *fe) | ||
412 | { | ||
413 | struct va1j5jf8007t_state *state; | ||
414 | u8 buf[2]; | ||
415 | struct i2c_msg msg; | ||
416 | int i; | ||
417 | |||
418 | state = fe->demodulator_priv; | ||
419 | |||
420 | msg.addr = state->config->demod_address; | ||
421 | msg.flags = 0; | ||
422 | msg.len = sizeof(buf); | ||
423 | msg.buf = buf; | ||
424 | |||
425 | for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_prepare_bufs); i++) { | ||
426 | memcpy(buf, va1j5jf8007t_prepare_bufs[i], sizeof(buf)); | ||
427 | if (i2c_transfer(state->adap, &msg, 1) != 1) | ||
428 | return -EREMOTEIO; | ||
429 | } | ||
430 | |||
431 | return va1j5jf8007t_init_frequency(state); | ||
432 | } | ||
433 | |||
434 | struct dvb_frontend * | ||
435 | va1j5jf8007t_attach(const struct va1j5jf8007t_config *config, | ||
436 | struct i2c_adapter *adap) | ||
437 | { | ||
438 | struct va1j5jf8007t_state *state; | ||
439 | struct dvb_frontend *fe; | ||
440 | u8 buf[2]; | ||
441 | struct i2c_msg msg; | ||
442 | |||
443 | state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL); | ||
444 | if (!state) | ||
445 | return NULL; | ||
446 | |||
447 | state->config = config; | ||
448 | state->adap = adap; | ||
449 | |||
450 | fe = &state->fe; | ||
451 | memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops)); | ||
452 | fe->demodulator_priv = state; | ||
453 | |||
454 | buf[0] = 0x01; | ||
455 | buf[1] = 0x80; | ||
456 | |||
457 | msg.addr = state->config->demod_address; | ||
458 | msg.flags = 0; | ||
459 | msg.len = sizeof(buf); | ||
460 | msg.buf = buf; | ||
461 | |||
462 | if (i2c_transfer(state->adap, &msg, 1) != 1) { | ||
463 | kfree(state); | ||
464 | return NULL; | ||
465 | } | ||
466 | |||
467 | return fe; | ||
468 | } | ||
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.h b/drivers/media/dvb/pt1/va1j5jf8007t.h new file mode 100644 index 000000000000..ed49906f7769 --- /dev/null +++ b/drivers/media/dvb/pt1/va1j5jf8007t.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * ISDB-T driver for VA1J5JF8007 | ||
3 | * | ||
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | ||
5 | * | ||
6 | * based on pt1dvr - http://pt1dvr.sourceforge.jp/ | ||
7 | * by Tomoaki Ishikawa <tomy@users.sourceforge.jp> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef VA1J5JF8007T_H | ||
25 | #define VA1J5JF8007T_H | ||
26 | |||
27 | struct va1j5jf8007t_config { | ||
28 | u8 demod_address; | ||
29 | }; | ||
30 | |||
31 | struct i2c_adapter; | ||
32 | |||
33 | struct dvb_frontend * | ||
34 | va1j5jf8007t_attach(const struct va1j5jf8007t_config *config, | ||
35 | struct i2c_adapter *adap); | ||
36 | |||
37 | /* must be called after va1j5jf8007s_attach */ | ||
38 | int va1j5jf8007t_prepare(struct dvb_frontend *fe); | ||
39 | |||
40 | #endif | ||