diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb/m920x.c')
-rw-r--r-- | drivers/media/usb/dvb-usb/m920x.c | 277 |
1 files changed, 227 insertions, 50 deletions
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index 661bb75be955..92afeb20650f 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "qt1010.h" | 16 | #include "qt1010.h" |
17 | #include "tda1004x.h" | 17 | #include "tda1004x.h" |
18 | #include "tda827x.h" | 18 | #include "tda827x.h" |
19 | #include "mt2060.h" | ||
19 | 20 | ||
20 | #include <media/tuner.h> | 21 | #include <media/tuner.h> |
21 | #include "tuner-simple.h" | 22 | #include "tuner-simple.h" |
@@ -63,23 +64,33 @@ static inline int m920x_write(struct usb_device *udev, u8 request, | |||
63 | return ret; | 64 | return ret; |
64 | } | 65 | } |
65 | 66 | ||
67 | static inline int m920x_write_seq(struct usb_device *udev, u8 request, | ||
68 | struct m920x_inits *seq) | ||
69 | { | ||
70 | int ret; | ||
71 | while (seq->address) { | ||
72 | ret = m920x_write(udev, request, seq->data, seq->address); | ||
73 | if (ret != 0) | ||
74 | return ret; | ||
75 | |||
76 | seq++; | ||
77 | } | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
66 | static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq) | 82 | static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq) |
67 | { | 83 | { |
68 | int ret = 0, i, epi, flags = 0; | 84 | int ret = 0, i, epi, flags = 0; |
69 | int adap_enabled[M9206_MAX_ADAPTERS] = { 0 }; | 85 | int adap_enabled[M9206_MAX_ADAPTERS] = { 0 }; |
70 | 86 | ||
71 | /* Remote controller init. */ | 87 | /* Remote controller init. */ |
72 | if (d->props.rc.legacy.rc_query) { | 88 | if (d->props.rc.legacy.rc_query || d->props.rc.core.rc_query) { |
73 | deb("Initialising remote control\n"); | 89 | deb("Initialising remote control\n"); |
74 | while (rc_seq->address) { | 90 | ret = m920x_write_seq(d->udev, M9206_CORE, rc_seq); |
75 | if ((ret = m920x_write(d->udev, M9206_CORE, | 91 | if (ret != 0) { |
76 | rc_seq->data, | 92 | deb("Initialising remote control failed\n"); |
77 | rc_seq->address)) != 0) { | 93 | return ret; |
78 | deb("Initialising remote control failed\n"); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | rc_seq++; | ||
83 | } | 94 | } |
84 | 95 | ||
85 | deb("Initialising remote control success\n"); | 96 | deb("Initialising remote control success\n"); |
@@ -130,9 +141,50 @@ static int m920x_init_ep(struct usb_interface *intf) | |||
130 | alt->desc.bAlternateSetting); | 141 | alt->desc.bAlternateSetting); |
131 | } | 142 | } |
132 | 143 | ||
133 | static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 144 | static inline void m920x_parse_rc_state(struct dvb_usb_device *d, u8 rc_state, |
145 | int *state) | ||
134 | { | 146 | { |
135 | struct m920x_state *m = d->priv; | 147 | struct m920x_state *m = d->priv; |
148 | |||
149 | switch (rc_state) { | ||
150 | case 0x80: | ||
151 | *state = REMOTE_NO_KEY_PRESSED; | ||
152 | break; | ||
153 | |||
154 | case 0x88: /* framing error or "invalid code" */ | ||
155 | case 0x99: | ||
156 | case 0xc0: | ||
157 | case 0xd8: | ||
158 | *state = REMOTE_NO_KEY_PRESSED; | ||
159 | m->rep_count = 0; | ||
160 | break; | ||
161 | |||
162 | case 0x93: | ||
163 | case 0x92: | ||
164 | case 0x83: /* pinnacle PCTV310e */ | ||
165 | case 0x82: | ||
166 | m->rep_count = 0; | ||
167 | *state = REMOTE_KEY_PRESSED; | ||
168 | break; | ||
169 | |||
170 | case 0x91: | ||
171 | case 0x81: /* pinnacle PCTV310e */ | ||
172 | /* prevent immediate auto-repeat */ | ||
173 | if (++m->rep_count > 2) | ||
174 | *state = REMOTE_KEY_REPEAT; | ||
175 | else | ||
176 | *state = REMOTE_NO_KEY_PRESSED; | ||
177 | break; | ||
178 | |||
179 | default: | ||
180 | deb("Unexpected rc state %02x\n", rc_state); | ||
181 | *state = REMOTE_NO_KEY_PRESSED; | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
187 | { | ||
136 | int i, ret = 0; | 188 | int i, ret = 0; |
137 | u8 *rc_state; | 189 | u8 *rc_state; |
138 | 190 | ||
@@ -140,51 +192,22 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
140 | if (!rc_state) | 192 | if (!rc_state) |
141 | return -ENOMEM; | 193 | return -ENOMEM; |
142 | 194 | ||
143 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) | 195 | ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, |
196 | rc_state, 1); | ||
197 | if (ret != 0) | ||
144 | goto out; | 198 | goto out; |
145 | 199 | ||
146 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) | 200 | ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, |
201 | rc_state + 1, 1); | ||
202 | if (ret != 0) | ||
147 | goto out; | 203 | goto out; |
148 | 204 | ||
205 | m920x_parse_rc_state(d, rc_state[0], state); | ||
206 | |||
149 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) | 207 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) |
150 | if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) { | 208 | if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) { |
151 | *event = d->props.rc.legacy.rc_map_table[i].keycode; | 209 | *event = d->props.rc.legacy.rc_map_table[i].keycode; |
152 | 210 | goto out; | |
153 | switch(rc_state[0]) { | ||
154 | case 0x80: | ||
155 | *state = REMOTE_NO_KEY_PRESSED; | ||
156 | goto out; | ||
157 | |||
158 | case 0x88: /* framing error or "invalid code" */ | ||
159 | case 0x99: | ||
160 | case 0xc0: | ||
161 | case 0xd8: | ||
162 | *state = REMOTE_NO_KEY_PRESSED; | ||
163 | m->rep_count = 0; | ||
164 | goto out; | ||
165 | |||
166 | case 0x93: | ||
167 | case 0x92: | ||
168 | case 0x83: /* pinnacle PCTV310e */ | ||
169 | case 0x82: | ||
170 | m->rep_count = 0; | ||
171 | *state = REMOTE_KEY_PRESSED; | ||
172 | goto out; | ||
173 | |||
174 | case 0x91: | ||
175 | case 0x81: /* pinnacle PCTV310e */ | ||
176 | /* prevent immediate auto-repeat */ | ||
177 | if (++m->rep_count > 2) | ||
178 | *state = REMOTE_KEY_REPEAT; | ||
179 | else | ||
180 | *state = REMOTE_NO_KEY_PRESSED; | ||
181 | goto out; | ||
182 | |||
183 | default: | ||
184 | deb("Unexpected rc state %02x\n", rc_state[0]); | ||
185 | *state = REMOTE_NO_KEY_PRESSED; | ||
186 | goto out; | ||
187 | } | ||
188 | } | 211 | } |
189 | 212 | ||
190 | if (rc_state[1] != 0) | 213 | if (rc_state[1] != 0) |
@@ -197,6 +220,38 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
197 | return ret; | 220 | return ret; |
198 | } | 221 | } |
199 | 222 | ||
223 | static int m920x_rc_core_query(struct dvb_usb_device *d) | ||
224 | { | ||
225 | int ret = 0; | ||
226 | u8 *rc_state; | ||
227 | int state; | ||
228 | |||
229 | rc_state = kmalloc(2, GFP_KERNEL); | ||
230 | if (!rc_state) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, &rc_state[0], 1)) != 0) | ||
234 | goto out; | ||
235 | |||
236 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, &rc_state[1], 1)) != 0) | ||
237 | goto out; | ||
238 | |||
239 | deb("state=0x%02x keycode=0x%02x\n", rc_state[0], rc_state[1]); | ||
240 | |||
241 | m920x_parse_rc_state(d, rc_state[0], &state); | ||
242 | |||
243 | if (state == REMOTE_NO_KEY_PRESSED) | ||
244 | rc_keyup(d->rc_dev); | ||
245 | else if (state == REMOTE_KEY_REPEAT) | ||
246 | rc_repeat(d->rc_dev); | ||
247 | else | ||
248 | rc_keydown(d->rc_dev, rc_state[1], 0); | ||
249 | |||
250 | out: | ||
251 | kfree(rc_state); | ||
252 | return ret; | ||
253 | } | ||
254 | |||
200 | /* I2C */ | 255 | /* I2C */ |
201 | static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | 256 | static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) |
202 | { | 257 | { |
@@ -496,6 +551,12 @@ static struct qt1010_config m920x_qt1010_config = { | |||
496 | .i2c_address = 0x62 | 551 | .i2c_address = 0x62 |
497 | }; | 552 | }; |
498 | 553 | ||
554 | static struct mt2060_config m920x_mt2060_config = { | ||
555 | .i2c_address = 0x60, /* 0xc0 */ | ||
556 | .clock_out = 0, | ||
557 | }; | ||
558 | |||
559 | |||
499 | /* Callbacks for DVB USB */ | 560 | /* Callbacks for DVB USB */ |
500 | static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) | 561 | static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) |
501 | { | 562 | { |
@@ -510,6 +571,37 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) | |||
510 | return 0; | 571 | return 0; |
511 | } | 572 | } |
512 | 573 | ||
574 | static int m920x_mt352_frontend_attach_vp7049(struct dvb_usb_adapter *adap) | ||
575 | { | ||
576 | struct m920x_inits vp7049_fe_init_seq[] = { | ||
577 | /* XXX without these commands the frontend cannot be detected, | ||
578 | * they must be sent BEFORE the frontend is attached */ | ||
579 | { 0xff28, 0x00 }, | ||
580 | { 0xff23, 0x00 }, | ||
581 | { 0xff28, 0x00 }, | ||
582 | { 0xff23, 0x00 }, | ||
583 | { 0xff21, 0x20 }, | ||
584 | { 0xff21, 0x60 }, | ||
585 | { 0xff28, 0x00 }, | ||
586 | { 0xff22, 0x00 }, | ||
587 | { 0xff20, 0x30 }, | ||
588 | { 0xff20, 0x20 }, | ||
589 | { 0xff20, 0x30 }, | ||
590 | { } /* terminating entry */ | ||
591 | }; | ||
592 | int ret; | ||
593 | |||
594 | deb("%s\n", __func__); | ||
595 | |||
596 | ret = m920x_write_seq(adap->dev->udev, M9206_CORE, vp7049_fe_init_seq); | ||
597 | if (ret != 0) { | ||
598 | deb("Initialization of vp7049 frontend failed."); | ||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | return m920x_mt352_frontend_attach(adap); | ||
603 | } | ||
604 | |||
513 | static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) | 605 | static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) |
514 | { | 606 | { |
515 | deb("%s\n",__func__); | 607 | deb("%s\n",__func__); |
@@ -574,6 +666,18 @@ static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | |||
574 | return 0; | 666 | return 0; |
575 | } | 667 | } |
576 | 668 | ||
669 | static int m920x_mt2060_tuner_attach(struct dvb_usb_adapter *adap) | ||
670 | { | ||
671 | deb("%s\n", __func__); | ||
672 | |||
673 | if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, | ||
674 | &m920x_mt2060_config, 1220) == NULL) | ||
675 | return -ENODEV; | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | |||
577 | /* device-specific initialization */ | 681 | /* device-specific initialization */ |
578 | static struct m920x_inits megasky_rc_init [] = { | 682 | static struct m920x_inits megasky_rc_init [] = { |
579 | { M9206_RC_INIT2, 0xa8 }, | 683 | { M9206_RC_INIT2, 0xa8 }, |
@@ -591,7 +695,7 @@ static struct m920x_inits tvwalkertwin_rc_init [] = { | |||
591 | }; | 695 | }; |
592 | 696 | ||
593 | static struct m920x_inits pinnacle310e_init[] = { | 697 | static struct m920x_inits pinnacle310e_init[] = { |
594 | /* without these the tuner don't work */ | 698 | /* without these the tuner doesn't work */ |
595 | { 0xff20, 0x9b }, | 699 | { 0xff20, 0x9b }, |
596 | { 0xff22, 0x70 }, | 700 | { 0xff22, 0x70 }, |
597 | 701 | ||
@@ -602,6 +706,15 @@ static struct m920x_inits pinnacle310e_init[] = { | |||
602 | { } /* terminating entry */ | 706 | { } /* terminating entry */ |
603 | }; | 707 | }; |
604 | 708 | ||
709 | static struct m920x_inits vp7049_rc_init[] = { | ||
710 | { 0xff28, 0x00 }, | ||
711 | { 0xff23, 0x00 }, | ||
712 | { 0xff21, 0x70 }, | ||
713 | { M9206_RC_INIT2, 0x00 }, | ||
714 | { M9206_RC_INIT1, 0xff }, | ||
715 | { } /* terminating entry */ | ||
716 | }; | ||
717 | |||
605 | /* ir keymaps */ | 718 | /* ir keymaps */ |
606 | static struct rc_map_table rc_map_megasky_table[] = { | 719 | static struct rc_map_table rc_map_megasky_table[] = { |
607 | { 0x0012, KEY_POWER }, | 720 | { 0x0012, KEY_POWER }, |
@@ -704,6 +817,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties; | |||
704 | static struct dvb_usb_device_properties tvwalkertwin_properties; | 817 | static struct dvb_usb_device_properties tvwalkertwin_properties; |
705 | static struct dvb_usb_device_properties dposh_properties; | 818 | static struct dvb_usb_device_properties dposh_properties; |
706 | static struct dvb_usb_device_properties pinnacle_pctv310e_properties; | 819 | static struct dvb_usb_device_properties pinnacle_pctv310e_properties; |
820 | static struct dvb_usb_device_properties vp7049_properties; | ||
707 | 821 | ||
708 | static int m920x_probe(struct usb_interface *intf, | 822 | static int m920x_probe(struct usb_interface *intf, |
709 | const struct usb_device_id *id) | 823 | const struct usb_device_id *id) |
@@ -756,6 +870,13 @@ static int m920x_probe(struct usb_interface *intf, | |||
756 | goto found; | 870 | goto found; |
757 | } | 871 | } |
758 | 872 | ||
873 | ret = dvb_usb_device_init(intf, &vp7049_properties, | ||
874 | THIS_MODULE, &d, adapter_nr); | ||
875 | if (ret == 0) { | ||
876 | rc_init_seq = vp7049_rc_init; | ||
877 | goto found; | ||
878 | } | ||
879 | |||
759 | return ret; | 880 | return ret; |
760 | } else { | 881 | } else { |
761 | /* Another interface on a multi-tuner device */ | 882 | /* Another interface on a multi-tuner device */ |
@@ -787,6 +908,7 @@ static struct usb_device_id m920x_table [] = { | |||
787 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, | 908 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, |
788 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, | 909 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, |
789 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) }, | 910 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) }, |
911 | { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_TWINHAN_VP7049) }, | ||
790 | { } /* Terminating entry */ | 912 | { } /* Terminating entry */ |
791 | }; | 913 | }; |
792 | MODULE_DEVICE_TABLE (usb, m920x_table); | 914 | MODULE_DEVICE_TABLE (usb, m920x_table); |
@@ -1079,6 +1201,61 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = { | |||
1079 | } | 1201 | } |
1080 | }; | 1202 | }; |
1081 | 1203 | ||
1204 | static struct dvb_usb_device_properties vp7049_properties = { | ||
1205 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1206 | |||
1207 | .usb_ctrl = DEVICE_SPECIFIC, | ||
1208 | .firmware = "dvb-usb-vp7049-0.95.fw", | ||
1209 | .download_firmware = m920x_firmware_download, | ||
1210 | |||
1211 | .rc.core = { | ||
1212 | .rc_interval = 150, | ||
1213 | .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, | ||
1214 | .rc_query = m920x_rc_core_query, | ||
1215 | .allowed_protos = RC_TYPE_UNKNOWN, | ||
1216 | }, | ||
1217 | |||
1218 | .size_of_priv = sizeof(struct m920x_state), | ||
1219 | |||
1220 | .identify_state = m920x_identify_state, | ||
1221 | .num_adapters = 1, | ||
1222 | .adapter = {{ | ||
1223 | .num_frontends = 1, | ||
1224 | .fe = {{ | ||
1225 | |||
1226 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
1227 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
1228 | |||
1229 | .pid_filter_count = 8, | ||
1230 | .pid_filter = m920x_pid_filter, | ||
1231 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
1232 | |||
1233 | .frontend_attach = m920x_mt352_frontend_attach_vp7049, | ||
1234 | .tuner_attach = m920x_mt2060_tuner_attach, | ||
1235 | |||
1236 | .stream = { | ||
1237 | .type = USB_BULK, | ||
1238 | .count = 8, | ||
1239 | .endpoint = 0x81, | ||
1240 | .u = { | ||
1241 | .bulk = { | ||
1242 | .buffersize = 512, | ||
1243 | } | ||
1244 | } | ||
1245 | }, | ||
1246 | } }, | ||
1247 | } }, | ||
1248 | .i2c_algo = &m920x_i2c_algo, | ||
1249 | |||
1250 | .num_device_descs = 1, | ||
1251 | .devices = { | ||
1252 | { "DTV-DVB UDTT7049", | ||
1253 | { &m920x_table[7], NULL }, | ||
1254 | { NULL }, | ||
1255 | } | ||
1256 | } | ||
1257 | }; | ||
1258 | |||
1082 | static struct usb_driver m920x_driver = { | 1259 | static struct usb_driver m920x_driver = { |
1083 | .name = "dvb_usb_m920x", | 1260 | .name = "dvb_usb_m920x", |
1084 | .probe = m920x_probe, | 1261 | .probe = m920x_probe, |