Add cxm(4), a driver for Hauppauge PVR-250/350 video capture cards.
[dragonfly.git] / sys / dev / video / cxm / cxm_msp34xxx.c
1 /*
2  * Copyright (c) 2003, 2004, 2005
3  *      John Wehle <john@feith.com>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by John Wehle.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /*
33  * Audio decoder routines for the Conexant MPEG-2 Codec driver.
34  *
35  * Ideally these routines should be implemented as a separate
36  * driver which has a generic audio decoder interface so that
37  * it's not necessary for each multimedia driver to re-invent
38  * the wheel.
39  */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/uio.h>
45 #include <sys/kernel.h>
46 #include <sys/poll.h>
47 #include <sys/select.h>
48 #include <sys/resource.h>
49 #include <sys/bus.h>
50 #include <sys/rman.h>
51
52 #include <machine/clock.h>
53
54 #include <dev/video/cxm/cxm.h>
55
56 #include <bus/iicbus/iiconf.h>
57 #include <bus/iicbus/iicbus.h>
58
59 #include "iicbb_if.h"
60
61
62 static const struct cxm_msp_command
63 msp34x5G_init = {
64         5,
65         {
66                 /* Enable Automatic Sound Select */
67                 { CXM_MSP3400C_DEM, 0x0030, { 0x20, 0x03 } },
68                 /* SCART Prescale = 0 dB */
69                 { CXM_MSP3400C_DFP, 0x000d, { 0x19, 0x00 } },
70                 /* FM / AM Prescale = 100 Khz and FM Matrix = Sound A Mono  */
71                 { CXM_MSP3400C_DFP, 0x000e, { 0x24, 0x03 } },
72                 /* NICAM Prescale = 9 dB  */
73                 { CXM_MSP3400C_DFP, 0x0010, { 0x5a, 0x00 } },
74                 /* Enable Automatic Standard Select */
75                 { CXM_MSP3400C_DEM, 0x0020, { 0x00, 0x01 } },
76         }
77 };
78
79 static const struct cxm_msp_command
80 msp34x5G_select_tuner = {
81         3,
82         {
83                 /* Loudspeaker Source = demodulator (St or A), Matrix = St */
84                 { CXM_MSP3400C_DFP, 0x0008, { 0x03, 0x20 } },
85                 /* SCART1_L/R Source = demodulator (St or A), Matrix = St */
86                 { CXM_MSP3400C_DFP, 0x000a, { 0x03, 0x20 } },
87                 /* DSP In = mute, SC1_OUT_L/R Source = SCART1_L/R */
88                 { CXM_MSP3400C_DFP, 0x0013, { 0x0f, 0x20 } }
89         }
90 };
91
92 static const struct cxm_msp_command
93 msp34x5D_init = {
94         4,
95         {
96                 /* Enable Automatic NICAM-FM/AM Switching */
97                 { CXM_MSP3400C_DEM, 0x0021, { 0x00, 0x01 } },
98                 /* SCART Prescale = 0 dB */
99                 { CXM_MSP3400C_DFP, 0x000d, { 0x19, 0x00 } },
100                 /* NICAM Prescale = 9 dB  */
101                 { CXM_MSP3400C_DFP, 0x0010, { 0x5a, 0x00 } },
102                 /* Enable Automatic Standard Select */
103                 { CXM_MSP3400C_DEM, 0x0020, { 0x00, 0x01 } },
104         }
105 };
106
107 static const struct cxm_msp_command
108 msp34x5D_select_tuner = {
109         5,
110         {
111                 /* Loudspeaker Source = demodulator (NICAM), Matrix = St */
112                 { CXM_MSP3400C_DFP, 0x0008, { 0x01, 0x20 } },
113                 /* SCART1_L/R Source = demodulator (NICAM), Matrix = St */
114                 { CXM_MSP3400C_DFP, 0x000a, { 0x01, 0x20 } },
115                 /* FM / AM Prescale = 100 Khz and FM Matrix = No Matrix  */
116                 { CXM_MSP3400C_DFP, 0x000e, { 0x24, 0x00 } },
117                 /* FM Deemphasis = 50 us */
118                 { CXM_MSP3400C_DFP, 0x000f, { 0x00, 0x00 } },
119                 /* DSP In = mute, SC1_OUT_L/R Source = SCART1_L/R */
120                 { CXM_MSP3400C_DFP, 0x0013, { 0x0f, 0x20 } }
121         }
122 };
123
124 static const struct cxm_msp_command
125 msp34xxx_mute = {
126         2,
127         {
128                 /* Loudspeaker volume = mute */
129                 { CXM_MSP3400C_DFP, 0x0000, { 0x00, 0x00 } },
130                 /* SC1_OUT_L/R volume = mute */
131                 { CXM_MSP3400C_DFP, 0x0007, { 0x00, 0x01 } }
132         }
133 };
134
135 static const struct cxm_msp_command
136 msp34xxx_unmute = {
137         2,
138         {
139                 /* Loudspeaker volume = 0 db */
140                 { CXM_MSP3400C_DFP, 0x0000, { 0x73, 0x00 } },
141                 /* SC1_OUT_L/R volume = 0 db */
142                 { CXM_MSP3400C_DFP, 0x0007, { 0x73, 0x01 } }
143         }
144 };
145
146 static const struct cxm_msp_command
147 msp34xxx_select_fm = {
148         3,
149         {
150                 /* Loudspeaker Source = SCART, Matrix = STEREO */
151                 { CXM_MSP3400C_DFP, 0x0008, { 0x02, 0x20 } },
152                 /* SCART1_L/R Source = SCART, Matrix = STEREO */
153                 { CXM_MSP3400C_DFP, 0x000a, { 0x02, 0x20 } },
154                 /* DSP In = SC2_IN_L/R, SC1_OUT_L/R Source = SCART1_L/R */
155                 { CXM_MSP3400C_DFP, 0x0013, { 0x0e, 0x00 } }
156         }
157 };
158
159 static const struct cxm_msp_command
160 msp34xxx_select_line_in = {
161         3,
162         {
163                 /* Loudspeaker Source = SCART, Matrix = STEREO */
164                 { CXM_MSP3400C_DFP, 0x0008, { 0x02, 0x20 } },
165                 /* SCART1_L/R Source = SCART, Matrix = STEREO */
166                 { CXM_MSP3400C_DFP, 0x000a, { 0x02, 0x20 } },
167                 /* DSP In = SC1_IN_L/R, SC1_OUT_L/R Source = SCART1_L/R */
168                 { CXM_MSP3400C_DFP, 0x0013, { 0x0c, 0x00 } }
169         }
170 };
171
172
173 /* Reset the MSP or DPL chip */
174 static int
175 cxm_msp_dpl_reset(device_t iicbus, int i2c_addr)
176 {
177         unsigned char msg[3];
178         int sent;
179
180         /* put into reset mode */
181         msg[0] = 0x00;
182         msg[1] = 0x80;
183         msg[2] = 0x00;
184
185         if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
186                 return -1;
187
188         if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
189             || sent != sizeof(msg))
190                 goto fail;
191
192         iicbus_stop(iicbus);
193
194         /* put back to operational mode */
195         msg[0] = 0x00;
196         msg[1] = 0x00;
197         msg[2] = 0x00;
198
199         if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
200                 return -1;
201
202         if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
203             || sent != sizeof(msg))
204                 goto fail;
205
206         iicbus_stop(iicbus);
207
208         return 0;
209
210 fail:
211         iicbus_stop(iicbus);
212         return -1;
213 }
214
215
216 /* Read from the MSP or DPL registers */
217 static int
218 cxm_msp_dpl_read(device_t iicbus, int i2c_addr,
219                   unsigned char dev, unsigned int addr,
220                   char *buf, int len)
221 {
222         unsigned char msg[3];
223         int received;
224         int sent;
225
226         msg[0] = (unsigned char)(dev + 1);
227         msg[1] = (unsigned char)(addr >> 8);
228         msg[2] = (unsigned char)addr;
229
230         if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
231                 return -1;
232
233         if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
234             || sent != sizeof(msg))
235                 goto fail;
236
237         if (iicbus_repeated_start(iicbus, i2c_addr + 1, CXM_I2C_TIMEOUT) != 0)
238                 goto fail;
239
240         if (iicbus_read(iicbus, buf, len, &received, IIC_LAST_READ, 0) != 0)
241                 goto fail;
242
243         iicbus_stop(iicbus);
244
245         return received;
246
247 fail:
248         iicbus_stop(iicbus);
249         return -1;
250 }
251
252
253 /* Write to the MSP or DPL registers */
254 static int
255 cxm_msp_dpl_write(device_t iicbus, int i2c_addr,
256                    unsigned char dev, unsigned int addr,
257                    const char *buf, int len)
258 {
259         unsigned char msg[3];
260         int sent;
261
262         msg[0] = (unsigned char)dev;
263         msg[1] = (unsigned char)(addr >> 8);
264         msg[2] = (unsigned char)addr;
265
266         if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
267                 return -1;
268
269         if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
270             || sent != sizeof(msg))
271                 goto fail;
272
273         if (iicbus_write(iicbus, buf, len, &sent, CXM_I2C_TIMEOUT) != 0)
274                 goto fail;
275
276         iicbus_stop(iicbus);
277
278         return sent;
279
280 fail:
281         iicbus_stop(iicbus);
282         return -1;
283 }
284
285
286 int
287 cxm_msp_init(struct cxm_softc *sc)
288 {
289         unsigned char rev1[2];
290         unsigned char rev2[2];
291         unsigned int i;
292         unsigned int nsettings;
293         const struct cxm_msp_setting *settings;
294
295         if (cxm_msp_dpl_reset (sc->iicbus, CXM_I2C_MSP3400) < 0)
296                 return -1;
297
298         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DFP,
299                              0x001e, rev1, sizeof(rev1)) != sizeof(rev1))
300                 return -1;
301
302         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DFP,
303                              0x001f, rev2, sizeof(rev2)) != sizeof(rev2))
304                 return -1;
305
306         ksnprintf(sc->msp_name, sizeof(sc->msp_name), "%c4%02d%c-%c%d",
307                  ((rev1[1] >> 4) & 0x0f) + '3', rev2[0],
308                  (rev1[1] & 0x0f) + '@', rev1[0] + '@', rev2[1] & 0x1f);
309
310         /*
311          * MSP 34x5D, 34x5G, and MSP 44x8G are the
312          * only audio decoders currently supported.
313          */
314
315         if (strncmp(&sc->msp_name[0], "34", 2) == 0
316             && strncmp(&sc->msp_name[3], "5D", 2) == 0)
317           ;
318         else if (strncmp(&sc->msp_name[0], "34", 2) == 0
319                  && strncmp(&sc->msp_name[3], "5G", 2) == 0)
320           ;
321         else if (strncmp(&sc->msp_name[0], "44", 2) == 0
322                  && strncmp(&sc->msp_name[3], "8G", 2) == 0)
323           ;
324         else {
325                 device_printf(sc->dev, "unknown audio decoder MSP%s\n",
326                     sc->msp_name);
327                 return -1;
328         }
329
330         nsettings = msp34x5G_init.nsettings;
331         settings = msp34x5G_init.settings;
332         if (sc->msp_name[4] == 'D') {
333                 nsettings = msp34x5D_init.nsettings;
334                 settings = msp34x5D_init.settings;
335           }
336
337         for (i = 0; i < nsettings; i++)
338                 if (cxm_msp_dpl_write(sc->iicbus, CXM_I2C_MSP3400,
339                                       settings[i].dev, settings[i].addr,
340                                       settings[i].value,
341                                       sizeof(settings[i].value))
342                     != sizeof(settings[i].value))
343                         return -1;
344
345         if (cxm_msp_select_source(sc, cxm_tuner_source) < 0)
346                 return -1;
347
348         device_printf(sc->dev, "MSP%s audio decoder\n", sc->msp_name);
349
350         return 0;
351 }
352
353
354 int
355 cxm_msp_mute(struct cxm_softc *sc)
356 {
357         unsigned int i;
358         unsigned int nsettings;
359         const struct cxm_msp_setting *settings;
360
361         nsettings = msp34xxx_mute.nsettings;
362         settings = msp34xxx_mute.settings;
363
364         for (i = 0; i < nsettings; i++)
365                 if (cxm_msp_dpl_write(sc->iicbus, CXM_I2C_MSP3400,
366                                       settings[i].dev, settings[i].addr,
367                                       settings[i].value,
368                                       sizeof(settings[i].value))
369                     != sizeof(settings[i].value))
370                         return -1;
371
372         return 0;
373 }
374
375
376 int
377 cxm_msp_unmute(struct cxm_softc *sc)
378 {
379         unsigned int i;
380         unsigned int nsettings;
381         const struct cxm_msp_setting *settings;
382
383         nsettings = msp34xxx_unmute.nsettings;
384         settings = msp34xxx_unmute.settings;
385
386         for (i = 0; i < nsettings; i++)
387                 if (cxm_msp_dpl_write(sc->iicbus, CXM_I2C_MSP3400,
388                                       settings[i].dev, settings[i].addr,
389                                       settings[i].value,
390                                       sizeof(settings[i].value))
391                     != sizeof(settings[i].value))
392                         return -1;
393
394         return 0;
395 }
396
397
398 int
399 cxm_msp_is_muted(struct cxm_softc *sc)
400 {
401         unsigned char volume[2];
402
403         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DFP,
404                              0x0000, volume, sizeof(volume)) != sizeof(volume))
405                 return -1;
406
407         return volume[0] == 0x00 || volume[0] == 0xff ? 1 : 0;
408 }
409
410
411 int
412 cxm_msp_select_source(struct cxm_softc *sc, enum cxm_source source)
413 {
414         unsigned int i;
415         unsigned int nsettings;
416         const struct cxm_msp_setting *settings;
417
418         switch (source) {
419         case cxm_fm_source:
420                 nsettings = msp34xxx_select_fm.nsettings;
421                 settings = msp34xxx_select_fm.settings;
422                 break;
423
424         case cxm_line_in_source_composite:
425         case cxm_line_in_source_svideo:
426                 nsettings = msp34xxx_select_line_in.nsettings;
427                 settings = msp34xxx_select_line_in.settings;
428                 break;
429
430         case cxm_tuner_source:
431                 nsettings = msp34x5G_select_tuner.nsettings;
432                 settings = msp34x5G_select_tuner.settings;
433                 if (sc->msp_name[4] == 'D') {
434                         nsettings = msp34x5D_select_tuner.nsettings;
435                         settings = msp34x5D_select_tuner.settings;
436                   }
437                 break;
438
439         default:
440                 return -1;
441         }
442
443         for (i = 0; i < nsettings; i++)
444                 if (cxm_msp_dpl_write(sc->iicbus, CXM_I2C_MSP3400,
445                                       settings[i].dev, settings[i].addr,
446                                       settings[i].value,
447                                       sizeof(settings[i].value))
448                     != sizeof(settings[i].value))
449                         return -1;
450
451         return 0;
452 }
453
454
455 enum cxm_source
456 cxm_msp_selected_source(struct cxm_softc *sc)
457 {
458         unsigned char dsp[2];
459         unsigned char source[2];
460
461         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DFP,
462                              0x0008, source, sizeof(source)) != sizeof(source))
463                 return cxm_unknown_source;
464
465         switch (source[0]) {
466         case 0: /* FM / AM mono signal */
467         case 1: /* Stereo or A / B */
468         case 3: /* Stereo or A */
469         case 4: /* Stereo or B */
470                 return cxm_tuner_source;
471
472         case 2: /* SCART */
473                 break;
474
475         default:
476                 return cxm_unknown_source;
477         }
478
479         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DFP,
480                              0x0013, dsp, sizeof(dsp)) != sizeof(dsp))
481                 return cxm_unknown_source;
482
483         if (dsp[1] & 0x20)
484                 return cxm_unknown_source;
485
486         switch (dsp[0] & 0x03) {
487         case 0:
488                 return cxm_line_in_source_composite;
489
490         case 2:
491                 return cxm_fm_source;
492
493         default:
494                  return cxm_unknown_source;
495         }
496 }
497
498
499 int
500 cxm_msp_autodetect_standard(struct cxm_softc *sc)
501 {
502         unsigned int i;
503         int locked;
504         unsigned int nsettings;
505         const struct cxm_msp_setting *settings;
506
507         switch (cxm_msp_selected_source(sc)) {
508         case cxm_tuner_source:
509                 break;
510
511         case cxm_fm_source:
512         case cxm_line_in_source_composite:
513         case cxm_line_in_source_svideo:
514                 return 1;
515
516         default:
517                 return -1;
518         }
519
520         /*
521          * Section 3.3.2.2 of the data sheet states:
522          *
523          *   A general refresh of the STANDARD SELECT
524          *   register is not allowed.
525          */
526
527         if (cxm_msp_dpl_reset (sc->iicbus, CXM_I2C_MSP3400) < 0)
528                 return -1;
529
530         nsettings = msp34x5G_init.nsettings;
531         settings = msp34x5G_init.settings;
532         if (sc->msp_name[4] == 'D') {
533                 nsettings = msp34x5D_init.nsettings;
534                 settings = msp34x5D_init.settings;
535           }
536
537         for (i = 0; i < nsettings; i++)
538                 if (cxm_msp_dpl_write(sc->iicbus, CXM_I2C_MSP3400,
539                                       settings[i].dev, settings[i].addr,
540                                       settings[i].value,
541                                       sizeof(settings[i].value))
542                     != sizeof(settings[i].value))
543                         return -1;
544
545         locked = cxm_msp_wait_for_lock(sc);
546
547         if (cxm_msp_select_source(sc, cxm_tuner_source) < 0)
548                 return -1;
549
550         return locked;
551 }
552
553
554 int
555 cxm_msp_is_locked(struct cxm_softc *sc)
556 {
557         unsigned char source[2];
558         unsigned char standard[2];
559
560         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DFP,
561                              0x0008, source, sizeof(source)) != sizeof(source))
562                 return -1;
563
564         switch (source[0]) {
565         case 0: /* FM / AM mono signal */
566         case 1: /* Stereo or A / B */
567         case 3: /* Stereo or A */
568         case 4: /* Stereo or B */
569                 break;
570
571         default:
572                 return 1;
573         }
574
575         if (cxm_msp_dpl_read(sc->iicbus, CXM_I2C_MSP3400, CXM_MSP3400C_DEM,
576                              0x007e, standard, sizeof(standard))
577             != sizeof(standard))
578                 return -1;
579
580         if (standard[0] >= 8 || (standard[0] == 0 && standard[1] == 0))
581                 return 0;
582
583         return 1;
584 }
585
586
587 int
588 cxm_msp_wait_for_lock(struct cxm_softc *sc)
589 {
590         unsigned int i;
591
592         /*
593          * Section 3.3.2.1 of the data sheet states:
594          *
595          *   Within 0.5 s the detection and setup of the actual
596          *   TV sound standard is performed.  The detected result
597          *   can be read out of the STANDARD RESULT register by
598          *   the control processor.
599          */
600
601         for (i = 0; i < 10; i++) {
602
603                 /*
604                  * The input may have just changed (prior to
605                  * cxm_msp_wait_for_lock) so start with the
606                  * delay to give the audio decoder a chance
607                  * to update its status.
608                  */
609
610                 tsleep(&sc->iicbus, 0, "audio", hz / 20);
611
612                 switch (cxm_msp_is_locked(sc)) {
613                 case 1:
614                         return 1;
615
616                 case 0:
617                         break;
618
619                 default:
620                         return -1;
621                 }
622         }
623
624         device_printf(sc->dev, "audio decoder failed to lock\n");
625
626         return 0;
627 }