GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / media / pci / cx18 / cx18-dvb.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  cx18 functions for DVB support
4  *
5  *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
6  *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
7  */
8
9 #include "cx18-version.h"
10 #include "cx18-dvb.h"
11 #include "cx18-io.h"
12 #include "cx18-queue.h"
13 #include "cx18-streams.h"
14 #include "cx18-cards.h"
15 #include "cx18-gpio.h"
16 #include "s5h1409.h"
17 #include "mxl5005s.h"
18 #include "s5h1411.h"
19 #include "tda18271.h"
20 #include "zl10353.h"
21
22 #include <linux/firmware.h>
23 #include "mt352.h"
24 #include "mt352_priv.h"
25 #include "tuner-xc2028.h"
26
27 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
28
29 #define FWFILE "/*(DEBLOBBED)*/"
30
31 #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
32 #define CX18_CLOCK_ENABLE2               0xc71024
33 #define CX18_DMUX_CLK_MASK               0x0080
34
35 /*
36  * CX18_CARD_HVR_1600_ESMT
37  * CX18_CARD_HVR_1600_SAMSUNG
38  */
39
40 static struct mxl5005s_config hauppauge_hvr1600_tuner = {
41         .i2c_address     = 0xC6 >> 1,
42         .if_freq         = IF_FREQ_5380000HZ,
43         .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
44         .agc_mode        = MXL_SINGLE_AGC,
45         .tracking_filter = MXL_TF_C_H,
46         .rssi_enable     = MXL_RSSI_ENABLE,
47         .cap_select      = MXL_CAP_SEL_ENABLE,
48         .div_out         = MXL_DIV_OUT_4,
49         .clock_out       = MXL_CLOCK_OUT_DISABLE,
50         .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
51         .top             = MXL5005S_TOP_25P2,
52         .mod_mode        = MXL_DIGITAL_MODE,
53         .if_mode         = MXL_ZERO_IF,
54         .qam_gain        = 0x02,
55         .AgcMasterByte   = 0x00,
56 };
57
58 static struct s5h1409_config hauppauge_hvr1600_config = {
59         .demod_address = 0x32 >> 1,
60         .output_mode   = S5H1409_SERIAL_OUTPUT,
61         .gpio          = S5H1409_GPIO_ON,
62         .qam_if        = 44000,
63         .inversion     = S5H1409_INVERSION_OFF,
64         .status_mode   = S5H1409_DEMODLOCKING,
65         .mpeg_timing   = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
66         .hvr1600_opt   = S5H1409_HVR1600_OPTIMIZE
67 };
68
69 /*
70  * CX18_CARD_HVR_1600_S5H1411
71  */
72 static struct s5h1411_config hcw_s5h1411_config = {
73         .output_mode   = S5H1411_SERIAL_OUTPUT,
74         .gpio          = S5H1411_GPIO_OFF,
75         .vsb_if        = S5H1411_IF_44000,
76         .qam_if        = S5H1411_IF_4000,
77         .inversion     = S5H1411_INVERSION_ON,
78         .status_mode   = S5H1411_DEMODLOCKING,
79         .mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
80 };
81
82 static struct tda18271_std_map hauppauge_tda18271_std_map = {
83         .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
84                       .if_lvl = 6, .rfagc_top = 0x37 },
85         .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
86                       .if_lvl = 6, .rfagc_top = 0x37 },
87 };
88
89 static struct tda18271_config hauppauge_tda18271_config = {
90         .std_map = &hauppauge_tda18271_std_map,
91         .gate    = TDA18271_GATE_DIGITAL,
92         .output_opt = TDA18271_OUTPUT_LT_OFF,
93 };
94
95 /*
96  * CX18_CARD_LEADTEK_DVR3100H
97  */
98 /* Information/confirmation of proper config values provided by Terry Wu */
99 static struct zl10353_config leadtek_dvr3100h_demod = {
100         .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
101         .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
102         .parallel_ts           = 1,         /* Not a serial TS */
103         .no_tuner              = 1,         /* XC3028 is not behind the gate */
104         .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
105 };
106
107 /*
108  * CX18_CARD_YUAN_MPC718
109  */
110 /*
111  * Due to
112  *
113  * 1. an absence of information on how to program the MT352
114  * 2. the Linux mt352 module pushing MT352 initialization off onto us here
115  *
116  * We have to use an init sequence that *you* must extract from the Windows
117  * driver (yuanrap.sys) and which we load as a firmware.
118  *
119  * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual
120  * with chip programming details, then I can remove this annoyance.
121  */
122 static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
123                                    const struct firmware **fw)
124 {
125         struct cx18 *cx = stream->cx;
126         const char *fn = FWFILE;
127         int ret;
128
129         ret = reject_firmware(fw, fn, &cx->pci_dev->dev);
130         if (ret)
131                 CX18_ERR("Unable to open firmware file %s\n", fn);
132         else {
133                 size_t sz = (*fw)->size;
134                 if (sz < 2 || sz > 64 || (sz % 2) != 0) {
135                         CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
136                                  fn, (unsigned long) sz);
137                         ret = -EILSEQ;
138                         release_firmware(*fw);
139                         *fw = NULL;
140                 }
141         }
142
143         if (ret) {
144                 CX18_ERR("The MPC718 board variant with the MT352 DVB-T demodulator will not work without it\n");
145                 CX18_ERR("Run 'linux/scripts/get_dvb_firmware mpc718' if you need the firmware\n");
146         }
147         return ret;
148 }
149
150 static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
151 {
152         struct cx18_dvb *dvb = container_of(fe->dvb,
153                                             struct cx18_dvb, dvb_adapter);
154         struct cx18_stream *stream = dvb->stream;
155         const struct firmware *fw = NULL;
156         int ret;
157         int i;
158         u8 buf[3];
159
160         ret = yuan_mpc718_mt352_reqfw(stream, &fw);
161         if (ret)
162                 return ret;
163
164         /* Loop through all the register-value pairs in the firmware file */
165         for (i = 0; i < fw->size; i += 2) {
166                 buf[0] = fw->data[i];
167                 /* Intercept a few registers we want to set ourselves */
168                 switch (buf[0]) {
169                 case TRL_NOMINAL_RATE_0:
170                         /* Set our custom OFDM bandwidth in the case below */
171                         break;
172                 case TRL_NOMINAL_RATE_1:
173                         /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
174                         /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
175                         /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
176                         buf[1] = 0x72;
177                         buf[2] = 0x49;
178                         mt352_write(fe, buf, 3);
179                         break;
180                 case INPUT_FREQ_0:
181                         /* Set our custom IF in the case below */
182                         break;
183                 case INPUT_FREQ_1:
184                         /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
185                         buf[1] = 0x31;
186                         buf[2] = 0xc0;
187                         mt352_write(fe, buf, 3);
188                         break;
189                 default:
190                         /* Pass through the register-value pair from the fw */
191                         buf[1] = fw->data[i+1];
192                         mt352_write(fe, buf, 2);
193                         break;
194                 }
195         }
196
197         buf[0] = (u8) TUNER_GO;
198         buf[1] = 0x01; /* Go */
199         mt352_write(fe, buf, 2);
200         release_firmware(fw);
201         return 0;
202 }
203
204 static struct mt352_config yuan_mpc718_mt352_demod = {
205         .demod_address = 0x1e >> 1,
206         .adc_clock     = 20480,     /* 20.480 MHz */
207         .if2           =  4560,     /*  4.560 MHz */
208         .no_tuner      = 1,         /* XC3028 is not behind the gate */
209         .demod_init    = yuan_mpc718_mt352_init,
210 };
211
212 static struct zl10353_config yuan_mpc718_zl10353_demod = {
213         .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
214         .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
215         .parallel_ts           = 1,         /* Not a serial TS */
216         .no_tuner              = 1,         /* XC3028 is not behind the gate */
217         .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
218 };
219
220 static struct zl10353_config gotview_dvd3_zl10353_demod = {
221         .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
222         .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
223         .parallel_ts           = 1,         /* Not a serial TS */
224         .no_tuner              = 1,         /* XC3028 is not behind the gate */
225         .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
226 };
227
228 static int dvb_register(struct cx18_stream *stream);
229
230 /* Kernel DVB framework calls this when the feed needs to start.
231  * The CX18 framework should enable the transport DMA handling
232  * and queue processing.
233  */
234 static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
235 {
236         struct dvb_demux *demux = feed->demux;
237         struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
238         struct cx18 *cx;
239         int ret;
240         u32 v;
241
242         if (!stream)
243                 return -EINVAL;
244
245         cx = stream->cx;
246         CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
247                         feed->pid, feed->index);
248
249         mutex_lock(&cx->serialize_lock);
250         ret = cx18_init_on_first_open(cx);
251         mutex_unlock(&cx->serialize_lock);
252         if (ret) {
253                 CX18_ERR("Failed to initialize firmware starting DVB feed\n");
254                 return ret;
255         }
256         ret = -EINVAL;
257
258         switch (cx->card->type) {
259         case CX18_CARD_HVR_1600_ESMT:
260         case CX18_CARD_HVR_1600_SAMSUNG:
261         case CX18_CARD_HVR_1600_S5H1411:
262                 v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
263                 v |= 0x00400000; /* Serial Mode */
264                 v |= 0x00002000; /* Data Length - Byte */
265                 v |= 0x00010000; /* Error - Polarity */
266                 v |= 0x00020000; /* Error - Passthru */
267                 v |= 0x000c0000; /* Error - Ignore */
268                 cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
269                 break;
270
271         case CX18_CARD_LEADTEK_DVR3100H:
272         case CX18_CARD_YUAN_MPC718:
273         case CX18_CARD_GOTVIEW_PCI_DVD3:
274         default:
275                 /* Assumption - Parallel transport - Signalling
276                  * undefined or default.
277                  */
278                 break;
279         }
280
281         if (!demux->dmx.frontend)
282                 return -EINVAL;
283
284         mutex_lock(&stream->dvb->feedlock);
285         if (stream->dvb->feeding++ == 0) {
286                 CX18_DEBUG_INFO("Starting Transport DMA\n");
287                 mutex_lock(&cx->serialize_lock);
288                 set_bit(CX18_F_S_STREAMING, &stream->s_flags);
289                 ret = cx18_start_v4l2_encode_stream(stream);
290                 if (ret < 0) {
291                         CX18_DEBUG_INFO("Failed to start Transport DMA\n");
292                         stream->dvb->feeding--;
293                         if (stream->dvb->feeding == 0)
294                                 clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
295                 }
296                 mutex_unlock(&cx->serialize_lock);
297         } else
298                 ret = 0;
299         mutex_unlock(&stream->dvb->feedlock);
300
301         return ret;
302 }
303
304 /* Kernel DVB framework calls this when the feed needs to stop. */
305 static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
306 {
307         struct dvb_demux *demux = feed->demux;
308         struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
309         struct cx18 *cx;
310         int ret = -EINVAL;
311
312         if (stream) {
313                 cx = stream->cx;
314                 CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
315                                 feed->pid, feed->index);
316
317                 mutex_lock(&stream->dvb->feedlock);
318                 if (--stream->dvb->feeding == 0) {
319                         CX18_DEBUG_INFO("Stopping Transport DMA\n");
320                         mutex_lock(&cx->serialize_lock);
321                         ret = cx18_stop_v4l2_encode_stream(stream, 0);
322                         mutex_unlock(&cx->serialize_lock);
323                 } else
324                         ret = 0;
325                 mutex_unlock(&stream->dvb->feedlock);
326         }
327
328         return ret;
329 }
330
331 int cx18_dvb_register(struct cx18_stream *stream)
332 {
333         struct cx18 *cx = stream->cx;
334         struct cx18_dvb *dvb = stream->dvb;
335         struct dvb_adapter *dvb_adapter;
336         struct dvb_demux *dvbdemux;
337         struct dmx_demux *dmx;
338         int ret;
339
340         if (!dvb)
341                 return -EINVAL;
342
343         dvb->enabled = 0;
344         dvb->stream = stream;
345
346         ret = dvb_register_adapter(&dvb->dvb_adapter,
347                         CX18_DRIVER_NAME,
348                         THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
349         if (ret < 0)
350                 goto err_out;
351
352         dvb_adapter = &dvb->dvb_adapter;
353
354         dvbdemux = &dvb->demux;
355
356         dvbdemux->priv = (void *)stream;
357
358         dvbdemux->filternum = 256;
359         dvbdemux->feednum = 256;
360         dvbdemux->start_feed = cx18_dvb_start_feed;
361         dvbdemux->stop_feed = cx18_dvb_stop_feed;
362         dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
363                 DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
364         ret = dvb_dmx_init(dvbdemux);
365         if (ret < 0)
366                 goto err_dvb_unregister_adapter;
367
368         dmx = &dvbdemux->dmx;
369
370         dvb->hw_frontend.source = DMX_FRONTEND_0;
371         dvb->mem_frontend.source = DMX_MEMORY_FE;
372         dvb->dmxdev.filternum = 256;
373         dvb->dmxdev.demux = dmx;
374
375         ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
376         if (ret < 0)
377                 goto err_dvb_dmx_release;
378
379         ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
380         if (ret < 0)
381                 goto err_dvb_dmxdev_release;
382
383         ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
384         if (ret < 0)
385                 goto err_remove_hw_frontend;
386
387         ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
388         if (ret < 0)
389                 goto err_remove_mem_frontend;
390
391         ret = dvb_register(stream);
392         if (ret < 0)
393                 goto err_disconnect_frontend;
394
395         dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
396
397         CX18_INFO("DVB Frontend registered\n");
398         CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
399                   stream->dvb->dvb_adapter.num, stream->name,
400                   stream->buffers, stream->buf_size/1024,
401                   (stream->buf_size * 100 / 1024) % 100);
402
403         mutex_init(&dvb->feedlock);
404         dvb->enabled = 1;
405         return ret;
406
407 err_disconnect_frontend:
408         dmx->disconnect_frontend(dmx);
409 err_remove_mem_frontend:
410         dmx->remove_frontend(dmx, &dvb->mem_frontend);
411 err_remove_hw_frontend:
412         dmx->remove_frontend(dmx, &dvb->hw_frontend);
413 err_dvb_dmxdev_release:
414         dvb_dmxdev_release(&dvb->dmxdev);
415 err_dvb_dmx_release:
416         dvb_dmx_release(dvbdemux);
417 err_dvb_unregister_adapter:
418         dvb_unregister_adapter(dvb_adapter);
419 err_out:
420         return ret;
421 }
422
423 void cx18_dvb_unregister(struct cx18_stream *stream)
424 {
425         struct cx18 *cx = stream->cx;
426         struct cx18_dvb *dvb = stream->dvb;
427         struct dvb_adapter *dvb_adapter;
428         struct dvb_demux *dvbdemux;
429         struct dmx_demux *dmx;
430
431         CX18_INFO("unregister DVB\n");
432
433         if (dvb == NULL || !dvb->enabled)
434                 return;
435
436         dvb_adapter = &dvb->dvb_adapter;
437         dvbdemux = &dvb->demux;
438         dmx = &dvbdemux->dmx;
439
440         dmx->close(dmx);
441         dvb_net_release(&dvb->dvbnet);
442         dmx->remove_frontend(dmx, &dvb->mem_frontend);
443         dmx->remove_frontend(dmx, &dvb->hw_frontend);
444         dvb_dmxdev_release(&dvb->dmxdev);
445         dvb_dmx_release(dvbdemux);
446         dvb_unregister_frontend(dvb->fe);
447         dvb_frontend_detach(dvb->fe);
448         dvb_unregister_adapter(dvb_adapter);
449 }
450
451 /* All the DVB attach calls go here, this function gets modified
452  * for each new card. cx18_dvb_start_feed() will also need changes.
453  */
454 static int dvb_register(struct cx18_stream *stream)
455 {
456         struct cx18_dvb *dvb = stream->dvb;
457         struct cx18 *cx = stream->cx;
458         int ret = 0;
459
460         switch (cx->card->type) {
461         case CX18_CARD_HVR_1600_ESMT:
462         case CX18_CARD_HVR_1600_SAMSUNG:
463                 dvb->fe = dvb_attach(s5h1409_attach,
464                         &hauppauge_hvr1600_config,
465                         &cx->i2c_adap[0]);
466                 if (dvb->fe != NULL) {
467                         dvb_attach(mxl5005s_attach, dvb->fe,
468                                 &cx->i2c_adap[0],
469                                 &hauppauge_hvr1600_tuner);
470                         ret = 0;
471                 }
472                 break;
473         case CX18_CARD_HVR_1600_S5H1411:
474                 dvb->fe = dvb_attach(s5h1411_attach,
475                                      &hcw_s5h1411_config,
476                                      &cx->i2c_adap[0]);
477                 if (dvb->fe != NULL)
478                         dvb_attach(tda18271_attach, dvb->fe,
479                                    0x60, &cx->i2c_adap[0],
480                                    &hauppauge_tda18271_config);
481                 break;
482         case CX18_CARD_LEADTEK_DVR3100H:
483                 dvb->fe = dvb_attach(zl10353_attach,
484                                      &leadtek_dvr3100h_demod,
485                                      &cx->i2c_adap[1]);
486                 if (dvb->fe != NULL) {
487                         struct dvb_frontend *fe;
488                         struct xc2028_config cfg = {
489                                 .i2c_adap = &cx->i2c_adap[1],
490                                 .i2c_addr = 0xc2 >> 1,
491                                 .ctrl = NULL,
492                         };
493                         static struct xc2028_ctrl ctrl = {
494                                 .fname   = "/*(DEBLOBBED)*/",
495                                 .max_len = 64,
496                                 .demod   = XC3028_FE_ZARLINK456,
497                                 .type    = XC2028_AUTO,
498                         };
499
500                         fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
501                         if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
502                                 fe->ops.tuner_ops.set_config(fe, &ctrl);
503                 }
504                 break;
505         case CX18_CARD_YUAN_MPC718:
506                 /*
507                  * TODO
508                  * Apparently, these cards also could instead have a
509                  * DiBcom demod supported by one of the db7000 drivers
510                  */
511                 dvb->fe = dvb_attach(mt352_attach,
512                                      &yuan_mpc718_mt352_demod,
513                                      &cx->i2c_adap[1]);
514                 if (dvb->fe == NULL)
515                         dvb->fe = dvb_attach(zl10353_attach,
516                                              &yuan_mpc718_zl10353_demod,
517                                              &cx->i2c_adap[1]);
518                 if (dvb->fe != NULL) {
519                         struct dvb_frontend *fe;
520                         struct xc2028_config cfg = {
521                                 .i2c_adap = &cx->i2c_adap[1],
522                                 .i2c_addr = 0xc2 >> 1,
523                                 .ctrl = NULL,
524                         };
525                         static struct xc2028_ctrl ctrl = {
526                                 .fname   = "/*(DEBLOBBED)*/",
527                                 .max_len = 64,
528                                 .demod   = XC3028_FE_ZARLINK456,
529                                 .type    = XC2028_AUTO,
530                         };
531
532                         fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
533                         if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
534                                 fe->ops.tuner_ops.set_config(fe, &ctrl);
535                 }
536                 break;
537         case CX18_CARD_GOTVIEW_PCI_DVD3:
538                         dvb->fe = dvb_attach(zl10353_attach,
539                                              &gotview_dvd3_zl10353_demod,
540                                              &cx->i2c_adap[1]);
541                 if (dvb->fe != NULL) {
542                         struct dvb_frontend *fe;
543                         struct xc2028_config cfg = {
544                                 .i2c_adap = &cx->i2c_adap[1],
545                                 .i2c_addr = 0xc2 >> 1,
546                                 .ctrl = NULL,
547                         };
548                         static struct xc2028_ctrl ctrl = {
549                                 .fname   = "/*(DEBLOBBED)*/",
550                                 .max_len = 64,
551                                 .demod   = XC3028_FE_ZARLINK456,
552                                 .type    = XC2028_AUTO,
553                         };
554
555                         fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
556                         if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
557                                 fe->ops.tuner_ops.set_config(fe, &ctrl);
558                 }
559                 break;
560         default:
561                 /* No Digital Tv Support */
562                 break;
563         }
564
565         if (dvb->fe == NULL) {
566                 CX18_ERR("frontend initialization failed\n");
567                 return -1;
568         }
569
570         dvb->fe->callback = cx18_reset_tuner_gpio;
571
572         ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
573         if (ret < 0) {
574                 if (dvb->fe->ops.release)
575                         dvb->fe->ops.release(dvb->fe);
576                 return ret;
577         }
578
579         /*
580          * The firmware seems to enable the TS DMUX clock
581          * under various circumstances.  However, since we know we
582          * might use it, let's just turn it on ourselves here.
583          */
584         cx18_write_reg_expect(cx,
585                               (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK,
586                               CX18_CLOCK_ENABLE2,
587                               CX18_DMUX_CLK_MASK,
588                               (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK);
589
590         return ret;
591 }
592
593 /*(DEBLOBBED)*/