aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/dvb-usb/m920x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/dvb-usb/m920x.c')
-rw-r--r--drivers/media/usb/dvb-usb/m920x.c277
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
67static 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
66static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq) 82static 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
133static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 144static 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
186static 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
223static 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
250out:
251 kfree(rc_state);
252 return ret;
253}
254
200/* I2C */ 255/* I2C */
201static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) 256static 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
554static 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 */
500static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) 561static 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
574static 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
513static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) 605static 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
669static 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 */
578static struct m920x_inits megasky_rc_init [] = { 682static 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
593static struct m920x_inits pinnacle310e_init[] = { 697static 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
709static 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 */
606static struct rc_map_table rc_map_megasky_table[] = { 719static 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;
704static struct dvb_usb_device_properties tvwalkertwin_properties; 817static struct dvb_usb_device_properties tvwalkertwin_properties;
705static struct dvb_usb_device_properties dposh_properties; 818static struct dvb_usb_device_properties dposh_properties;
706static struct dvb_usb_device_properties pinnacle_pctv310e_properties; 819static struct dvb_usb_device_properties pinnacle_pctv310e_properties;
820static struct dvb_usb_device_properties vp7049_properties;
707 821
708static int m920x_probe(struct usb_interface *intf, 822static 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};
792MODULE_DEVICE_TABLE (usb, m920x_table); 914MODULE_DEVICE_TABLE (usb, m920x_table);
@@ -1079,6 +1201,61 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
1079 } 1201 }
1080}; 1202};
1081 1203
1204static 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
1082static struct usb_driver m920x_driver = { 1259static struct usb_driver m920x_driver = {
1083 .name = "dvb_usb_m920x", 1260 .name = "dvb_usb_m920x",
1084 .probe = m920x_probe, 1261 .probe = m920x_probe,