162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * device driver for Conexant 2388x based TV cards 462306a36Sopenharmony_ci * MPEG Transport Stream (DVB) routines 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> 762306a36Sopenharmony_ci * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "cx88.h" 1162306a36Sopenharmony_ci#include "dvb-pll.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/init.h> 1562306a36Sopenharmony_ci#include <linux/device.h> 1662306a36Sopenharmony_ci#include <linux/fs.h> 1762306a36Sopenharmony_ci#include <linux/kthread.h> 1862306a36Sopenharmony_ci#include <linux/file.h> 1962306a36Sopenharmony_ci#include <linux/suspend.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <media/v4l2-common.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "mt352.h" 2462306a36Sopenharmony_ci#include "mt352_priv.h" 2562306a36Sopenharmony_ci#include "cx88-vp3054-i2c.h" 2662306a36Sopenharmony_ci#include "zl10353.h" 2762306a36Sopenharmony_ci#include "cx22702.h" 2862306a36Sopenharmony_ci#include "or51132.h" 2962306a36Sopenharmony_ci#include "lgdt330x.h" 3062306a36Sopenharmony_ci#include "s5h1409.h" 3162306a36Sopenharmony_ci#include "xc4000.h" 3262306a36Sopenharmony_ci#include "xc5000.h" 3362306a36Sopenharmony_ci#include "nxt200x.h" 3462306a36Sopenharmony_ci#include "cx24123.h" 3562306a36Sopenharmony_ci#include "isl6421.h" 3662306a36Sopenharmony_ci#include "tuner-simple.h" 3762306a36Sopenharmony_ci#include "tda9887.h" 3862306a36Sopenharmony_ci#include "s5h1411.h" 3962306a36Sopenharmony_ci#include "stv0299.h" 4062306a36Sopenharmony_ci#include "z0194a.h" 4162306a36Sopenharmony_ci#include "stv0288.h" 4262306a36Sopenharmony_ci#include "stb6000.h" 4362306a36Sopenharmony_ci#include "cx24116.h" 4462306a36Sopenharmony_ci#include "stv0900.h" 4562306a36Sopenharmony_ci#include "stb6100.h" 4662306a36Sopenharmony_ci#include "stb6100_proc.h" 4762306a36Sopenharmony_ci#include "mb86a16.h" 4862306a36Sopenharmony_ci#include "ts2020.h" 4962306a36Sopenharmony_ci#include "ds3000.h" 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciMODULE_DESCRIPTION("driver for cx2388x based DVB cards"); 5262306a36Sopenharmony_ciMODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); 5362306a36Sopenharmony_ciMODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); 5462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 5562306a36Sopenharmony_ciMODULE_VERSION(CX88_VERSION); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic unsigned int debug; 5862306a36Sopenharmony_cimodule_param(debug, int, 0644); 5962306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "enable debug messages [dvb]"); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic unsigned int dvb_buf_tscnt = 32; 6262306a36Sopenharmony_cimodule_param(dvb_buf_tscnt, int, 0644); 6362306a36Sopenharmony_ciMODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]"); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define dprintk(level, fmt, arg...) do { \ 6862306a36Sopenharmony_ci if (debug >= level) \ 6962306a36Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: dvb:" fmt), \ 7062306a36Sopenharmony_ci __func__, ##arg); \ 7162306a36Sopenharmony_ci} while (0) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic int queue_setup(struct vb2_queue *q, 7662306a36Sopenharmony_ci unsigned int *num_buffers, unsigned int *num_planes, 7762306a36Sopenharmony_ci unsigned int sizes[], struct device *alloc_devs[]) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct cx8802_dev *dev = q->drv_priv; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci *num_planes = 1; 8262306a36Sopenharmony_ci dev->ts_packet_size = 188 * 4; 8362306a36Sopenharmony_ci dev->ts_packet_count = dvb_buf_tscnt; 8462306a36Sopenharmony_ci sizes[0] = dev->ts_packet_size * dev->ts_packet_count; 8562306a36Sopenharmony_ci *num_buffers = dvb_buf_tscnt; 8662306a36Sopenharmony_ci return 0; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic int buffer_prepare(struct vb2_buffer *vb) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 9262306a36Sopenharmony_ci struct cx8802_dev *dev = vb->vb2_queue->drv_priv; 9362306a36Sopenharmony_ci struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci return cx8802_buf_prepare(vb->vb2_queue, dev, buf); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic void buffer_finish(struct vb2_buffer *vb) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 10162306a36Sopenharmony_ci struct cx8802_dev *dev = vb->vb2_queue->drv_priv; 10262306a36Sopenharmony_ci struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); 10362306a36Sopenharmony_ci struct cx88_riscmem *risc = &buf->risc; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (risc->cpu) 10662306a36Sopenharmony_ci dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu, 10762306a36Sopenharmony_ci risc->dma); 10862306a36Sopenharmony_ci memset(risc, 0, sizeof(*risc)); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void buffer_queue(struct vb2_buffer *vb) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 11462306a36Sopenharmony_ci struct cx8802_dev *dev = vb->vb2_queue->drv_priv; 11562306a36Sopenharmony_ci struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci cx8802_buf_queue(dev, buf); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int start_streaming(struct vb2_queue *q, unsigned int count) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct cx8802_dev *dev = q->drv_priv; 12362306a36Sopenharmony_ci struct cx88_dmaqueue *dmaq = &dev->mpegq; 12462306a36Sopenharmony_ci struct cx88_buffer *buf; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci buf = list_entry(dmaq->active.next, struct cx88_buffer, list); 12762306a36Sopenharmony_ci cx8802_start_dma(dev, dmaq, buf); 12862306a36Sopenharmony_ci return 0; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic void stop_streaming(struct vb2_queue *q) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct cx8802_dev *dev = q->drv_priv; 13462306a36Sopenharmony_ci struct cx88_dmaqueue *dmaq = &dev->mpegq; 13562306a36Sopenharmony_ci unsigned long flags; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci cx8802_cancel_buffers(dev); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci spin_lock_irqsave(&dev->slock, flags); 14062306a36Sopenharmony_ci while (!list_empty(&dmaq->active)) { 14162306a36Sopenharmony_ci struct cx88_buffer *buf = list_entry(dmaq->active.next, 14262306a36Sopenharmony_ci struct cx88_buffer, list); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci list_del(&buf->list); 14562306a36Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->slock, flags); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic const struct vb2_ops dvb_qops = { 15162306a36Sopenharmony_ci .queue_setup = queue_setup, 15262306a36Sopenharmony_ci .buf_prepare = buffer_prepare, 15362306a36Sopenharmony_ci .buf_finish = buffer_finish, 15462306a36Sopenharmony_ci .buf_queue = buffer_queue, 15562306a36Sopenharmony_ci .wait_prepare = vb2_ops_wait_prepare, 15662306a36Sopenharmony_ci .wait_finish = vb2_ops_wait_finish, 15762306a36Sopenharmony_ci .start_streaming = start_streaming, 15862306a36Sopenharmony_ci .stop_streaming = stop_streaming, 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int cx88_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 16662306a36Sopenharmony_ci struct cx8802_driver *drv = NULL; 16762306a36Sopenharmony_ci int ret = 0; 16862306a36Sopenharmony_ci int fe_id; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci fe_id = vb2_dvb_find_frontend(&dev->frontends, fe); 17162306a36Sopenharmony_ci if (!fe_id) { 17262306a36Sopenharmony_ci pr_err("%s() No frontend found\n", __func__); 17362306a36Sopenharmony_ci return -EINVAL; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci mutex_lock(&dev->core->lock); 17762306a36Sopenharmony_ci drv = cx8802_get_driver(dev, CX88_MPEG_DVB); 17862306a36Sopenharmony_ci if (drv) { 17962306a36Sopenharmony_ci if (acquire) { 18062306a36Sopenharmony_ci dev->frontends.active_fe_id = fe_id; 18162306a36Sopenharmony_ci ret = drv->request_acquire(drv); 18262306a36Sopenharmony_ci } else { 18362306a36Sopenharmony_ci ret = drv->request_release(drv); 18462306a36Sopenharmony_ci dev->frontends.active_fe_id = 0; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci mutex_unlock(&dev->core->lock); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return ret; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct vb2_dvb_frontends *f; 19562306a36Sopenharmony_ci struct vb2_dvb_frontend *fe; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (!core->dvbdev) 19862306a36Sopenharmony_ci return; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci f = &core->dvbdev->frontends; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci if (!f) 20362306a36Sopenharmony_ci return; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (f->gate <= 1) /* undefined or fe0 */ 20662306a36Sopenharmony_ci fe = vb2_dvb_get_frontend(f, 1); 20762306a36Sopenharmony_ci else 20862306a36Sopenharmony_ci fe = vb2_dvb_get_frontend(f, f->gate); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) 21162306a36Sopenharmony_ci fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/* ------------------------------------------------------------------ */ 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic int dvico_fusionhdtv_demod_init(struct dvb_frontend *fe) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci static const u8 clock_config[] = { CLOCK_CTL, 0x38, 0x39 }; 21962306a36Sopenharmony_ci static const u8 reset[] = { RESET, 0x80 }; 22062306a36Sopenharmony_ci static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 22162306a36Sopenharmony_ci static const u8 agc_cfg[] = { AGC_TARGET, 0x24, 0x20 }; 22262306a36Sopenharmony_ci static const u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; 22362306a36Sopenharmony_ci static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 22662306a36Sopenharmony_ci udelay(200); 22762306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 22862306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 23162306a36Sopenharmony_ci mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); 23262306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 23362306a36Sopenharmony_ci return 0; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic int dvico_dual_demod_init(struct dvb_frontend *fe) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci static const u8 clock_config[] = { CLOCK_CTL, 0x38, 0x38 }; 23962306a36Sopenharmony_ci static const u8 reset[] = { RESET, 0x80 }; 24062306a36Sopenharmony_ci static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; 24162306a36Sopenharmony_ci static const u8 agc_cfg[] = { AGC_TARGET, 0x28, 0x20 }; 24262306a36Sopenharmony_ci static const u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; 24362306a36Sopenharmony_ci static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 24662306a36Sopenharmony_ci udelay(200); 24762306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 24862306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 25162306a36Sopenharmony_ci mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); 25262306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return 0; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int dntv_live_dvbt_demod_init(struct dvb_frontend *fe) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci static const u8 clock_config[] = { 0x89, 0x38, 0x39 }; 26062306a36Sopenharmony_ci static const u8 reset[] = { 0x50, 0x80 }; 26162306a36Sopenharmony_ci static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 }; 26262306a36Sopenharmony_ci static const u8 agc_cfg[] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, 26362306a36Sopenharmony_ci 0x00, 0xFF, 0x00, 0x40, 0x40 }; 26462306a36Sopenharmony_ci static const u8 dntv_extra[] = { 0xB5, 0x7A }; 26562306a36Sopenharmony_ci static const u8 capt_range_cfg[] = { 0x75, 0x32 }; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 26862306a36Sopenharmony_ci udelay(2000); 26962306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 27062306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 27362306a36Sopenharmony_ci udelay(2000); 27462306a36Sopenharmony_ci mt352_write(fe, dntv_extra, sizeof(dntv_extra)); 27562306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic const struct mt352_config dvico_fusionhdtv = { 28162306a36Sopenharmony_ci .demod_address = 0x0f, 28262306a36Sopenharmony_ci .demod_init = dvico_fusionhdtv_demod_init, 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic const struct mt352_config dntv_live_dvbt_config = { 28662306a36Sopenharmony_ci .demod_address = 0x0f, 28762306a36Sopenharmony_ci .demod_init = dntv_live_dvbt_demod_init, 28862306a36Sopenharmony_ci}; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic const struct mt352_config dvico_fusionhdtv_dual = { 29162306a36Sopenharmony_ci .demod_address = 0x0f, 29262306a36Sopenharmony_ci .demod_init = dvico_dual_demod_init, 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { 29662306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 29762306a36Sopenharmony_ci .no_tuner = 1, 29862306a36Sopenharmony_ci .if2 = 45600, 29962306a36Sopenharmony_ci}; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic const struct mb86a16_config twinhan_vp1027 = { 30262306a36Sopenharmony_ci .demod_address = 0x08, 30362306a36Sopenharmony_ci}; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) 30662306a36Sopenharmony_cistatic int dntv_live_dvbt_pro_demod_init(struct dvb_frontend *fe) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci static const u8 clock_config[] = { 0x89, 0x38, 0x38 }; 30962306a36Sopenharmony_ci static const u8 reset[] = { 0x50, 0x80 }; 31062306a36Sopenharmony_ci static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 }; 31162306a36Sopenharmony_ci static const u8 agc_cfg[] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, 31262306a36Sopenharmony_ci 0x00, 0xFF, 0x00, 0x40, 0x40 }; 31362306a36Sopenharmony_ci static const u8 dntv_extra[] = { 0xB5, 0x7A }; 31462306a36Sopenharmony_ci static const u8 capt_range_cfg[] = { 0x75, 0x32 }; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci mt352_write(fe, clock_config, sizeof(clock_config)); 31762306a36Sopenharmony_ci udelay(2000); 31862306a36Sopenharmony_ci mt352_write(fe, reset, sizeof(reset)); 31962306a36Sopenharmony_ci mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci mt352_write(fe, agc_cfg, sizeof(agc_cfg)); 32262306a36Sopenharmony_ci udelay(2000); 32362306a36Sopenharmony_ci mt352_write(fe, dntv_extra, sizeof(dntv_extra)); 32462306a36Sopenharmony_ci mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci return 0; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic const struct mt352_config dntv_live_dvbt_pro_config = { 33062306a36Sopenharmony_ci .demod_address = 0x0f, 33162306a36Sopenharmony_ci .no_tuner = 1, 33262306a36Sopenharmony_ci .demod_init = dntv_live_dvbt_pro_demod_init, 33362306a36Sopenharmony_ci}; 33462306a36Sopenharmony_ci#endif 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic const struct zl10353_config dvico_fusionhdtv_hybrid = { 33762306a36Sopenharmony_ci .demod_address = 0x0f, 33862306a36Sopenharmony_ci .no_tuner = 1, 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic const struct zl10353_config dvico_fusionhdtv_xc3028 = { 34262306a36Sopenharmony_ci .demod_address = 0x0f, 34362306a36Sopenharmony_ci .if2 = 45600, 34462306a36Sopenharmony_ci .no_tuner = 1, 34562306a36Sopenharmony_ci}; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { 34862306a36Sopenharmony_ci .demod_address = 0x0f, 34962306a36Sopenharmony_ci .if2 = 4560, 35062306a36Sopenharmony_ci .no_tuner = 1, 35162306a36Sopenharmony_ci .demod_init = dvico_fusionhdtv_demod_init, 35262306a36Sopenharmony_ci}; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_cistatic const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { 35562306a36Sopenharmony_ci .demod_address = 0x0f, 35662306a36Sopenharmony_ci}; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic const struct cx22702_config connexant_refboard_config = { 35962306a36Sopenharmony_ci .demod_address = 0x43, 36062306a36Sopenharmony_ci .output_mode = CX22702_SERIAL_OUTPUT, 36162306a36Sopenharmony_ci}; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic const struct cx22702_config hauppauge_hvr_config = { 36462306a36Sopenharmony_ci .demod_address = 0x63, 36562306a36Sopenharmony_ci .output_mode = CX22702_SERIAL_OUTPUT, 36662306a36Sopenharmony_ci}; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic int or51132_set_ts_param(struct dvb_frontend *fe, int is_punctured) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; 37362306a36Sopenharmony_ci return 0; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic const struct or51132_config pchdtv_hd3000 = { 37762306a36Sopenharmony_ci .demod_address = 0x15, 37862306a36Sopenharmony_ci .set_ts_params = or51132_set_ts_param, 37962306a36Sopenharmony_ci}; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cistatic int lgdt330x_pll_rf_set(struct dvb_frontend *fe, int index) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 38462306a36Sopenharmony_ci struct cx88_core *core = dev->core; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci dprintk(1, "%s: index = %d\n", __func__, index); 38762306a36Sopenharmony_ci if (index == 0) 38862306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 8); 38962306a36Sopenharmony_ci else 39062306a36Sopenharmony_ci cx_set(MO_GP0_IO, 8); 39162306a36Sopenharmony_ci return 0; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic int lgdt330x_set_ts_param(struct dvb_frontend *fe, int is_punctured) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (is_punctured) 39962306a36Sopenharmony_ci dev->ts_gen_cntrl |= 0x04; 40062306a36Sopenharmony_ci else 40162306a36Sopenharmony_ci dev->ts_gen_cntrl &= ~0x04; 40262306a36Sopenharmony_ci return 0; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic struct lgdt330x_config fusionhdtv_3_gold = { 40662306a36Sopenharmony_ci .demod_chip = LGDT3302, 40762306a36Sopenharmony_ci .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ 40862306a36Sopenharmony_ci .set_ts_params = lgdt330x_set_ts_param, 40962306a36Sopenharmony_ci}; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic const struct lgdt330x_config fusionhdtv_5_gold = { 41262306a36Sopenharmony_ci .demod_chip = LGDT3303, 41362306a36Sopenharmony_ci .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ 41462306a36Sopenharmony_ci .set_ts_params = lgdt330x_set_ts_param, 41562306a36Sopenharmony_ci}; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic const struct lgdt330x_config pchdtv_hd5500 = { 41862306a36Sopenharmony_ci .demod_chip = LGDT3303, 41962306a36Sopenharmony_ci .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ 42062306a36Sopenharmony_ci .set_ts_params = lgdt330x_set_ts_param, 42162306a36Sopenharmony_ci}; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic int nxt200x_set_ts_param(struct dvb_frontend *fe, int is_punctured) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; 42862306a36Sopenharmony_ci return 0; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic const struct nxt200x_config ati_hdtvwonder = { 43262306a36Sopenharmony_ci .demod_address = 0x0a, 43362306a36Sopenharmony_ci .set_ts_params = nxt200x_set_ts_param, 43462306a36Sopenharmony_ci}; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int cx24123_set_ts_param(struct dvb_frontend *fe, 43762306a36Sopenharmony_ci int is_punctured) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x02; 44262306a36Sopenharmony_ci return 0; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic int kworld_dvbs_100_set_voltage(struct dvb_frontend *fe, 44662306a36Sopenharmony_ci enum fe_sec_voltage voltage) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 44962306a36Sopenharmony_ci struct cx88_core *core = dev->core; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (voltage == SEC_VOLTAGE_OFF) 45262306a36Sopenharmony_ci cx_write(MO_GP0_IO, 0x000006fb); 45362306a36Sopenharmony_ci else 45462306a36Sopenharmony_ci cx_write(MO_GP0_IO, 0x000006f9); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (core->prev_set_voltage) 45762306a36Sopenharmony_ci return core->prev_set_voltage(fe, voltage); 45862306a36Sopenharmony_ci return 0; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, 46262306a36Sopenharmony_ci enum fe_sec_voltage voltage) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 46562306a36Sopenharmony_ci struct cx88_core *core = dev->core; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (voltage == SEC_VOLTAGE_OFF) { 46862306a36Sopenharmony_ci dprintk(1, "LNB Voltage OFF\n"); 46962306a36Sopenharmony_ci cx_write(MO_GP0_IO, 0x0000efff); 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (core->prev_set_voltage) 47362306a36Sopenharmony_ci return core->prev_set_voltage(fe, voltage); 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic int tevii_dvbs_set_voltage(struct dvb_frontend *fe, 47862306a36Sopenharmony_ci enum fe_sec_voltage voltage) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 48162306a36Sopenharmony_ci struct cx88_core *core = dev->core; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x6040); 48462306a36Sopenharmony_ci switch (voltage) { 48562306a36Sopenharmony_ci case SEC_VOLTAGE_13: 48662306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x20); 48762306a36Sopenharmony_ci break; 48862306a36Sopenharmony_ci case SEC_VOLTAGE_18: 48962306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x20); 49062306a36Sopenharmony_ci break; 49162306a36Sopenharmony_ci case SEC_VOLTAGE_OFF: 49262306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x20); 49362306a36Sopenharmony_ci break; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci if (core->prev_set_voltage) 49762306a36Sopenharmony_ci return core->prev_set_voltage(fe, voltage); 49862306a36Sopenharmony_ci return 0; 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic int vp1027_set_voltage(struct dvb_frontend *fe, 50262306a36Sopenharmony_ci enum fe_sec_voltage voltage) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 50562306a36Sopenharmony_ci struct cx88_core *core = dev->core; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci switch (voltage) { 50862306a36Sopenharmony_ci case SEC_VOLTAGE_13: 50962306a36Sopenharmony_ci dprintk(1, "LNB SEC Voltage=13\n"); 51062306a36Sopenharmony_ci cx_write(MO_GP0_IO, 0x00001220); 51162306a36Sopenharmony_ci break; 51262306a36Sopenharmony_ci case SEC_VOLTAGE_18: 51362306a36Sopenharmony_ci dprintk(1, "LNB SEC Voltage=18\n"); 51462306a36Sopenharmony_ci cx_write(MO_GP0_IO, 0x00001222); 51562306a36Sopenharmony_ci break; 51662306a36Sopenharmony_ci case SEC_VOLTAGE_OFF: 51762306a36Sopenharmony_ci dprintk(1, "LNB Voltage OFF\n"); 51862306a36Sopenharmony_ci cx_write(MO_GP0_IO, 0x00001230); 51962306a36Sopenharmony_ci break; 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (core->prev_set_voltage) 52362306a36Sopenharmony_ci return core->prev_set_voltage(fe, voltage); 52462306a36Sopenharmony_ci return 0; 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic const struct cx24123_config geniatech_dvbs_config = { 52862306a36Sopenharmony_ci .demod_address = 0x55, 52962306a36Sopenharmony_ci .set_ts_params = cx24123_set_ts_param, 53062306a36Sopenharmony_ci}; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic const struct cx24123_config hauppauge_novas_config = { 53362306a36Sopenharmony_ci .demod_address = 0x55, 53462306a36Sopenharmony_ci .set_ts_params = cx24123_set_ts_param, 53562306a36Sopenharmony_ci}; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic const struct cx24123_config kworld_dvbs_100_config = { 53862306a36Sopenharmony_ci .demod_address = 0x15, 53962306a36Sopenharmony_ci .set_ts_params = cx24123_set_ts_param, 54062306a36Sopenharmony_ci .lnb_polarity = 1, 54162306a36Sopenharmony_ci}; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic const struct s5h1409_config pinnacle_pctv_hd_800i_config = { 54462306a36Sopenharmony_ci .demod_address = 0x32 >> 1, 54562306a36Sopenharmony_ci .output_mode = S5H1409_PARALLEL_OUTPUT, 54662306a36Sopenharmony_ci .gpio = S5H1409_GPIO_ON, 54762306a36Sopenharmony_ci .qam_if = 44000, 54862306a36Sopenharmony_ci .inversion = S5H1409_INVERSION_OFF, 54962306a36Sopenharmony_ci .status_mode = S5H1409_DEMODLOCKING, 55062306a36Sopenharmony_ci .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINUOUS_NONINVERTING_CLOCK, 55162306a36Sopenharmony_ci}; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_cistatic const struct s5h1409_config dvico_hdtv5_pci_nano_config = { 55462306a36Sopenharmony_ci .demod_address = 0x32 >> 1, 55562306a36Sopenharmony_ci .output_mode = S5H1409_SERIAL_OUTPUT, 55662306a36Sopenharmony_ci .gpio = S5H1409_GPIO_OFF, 55762306a36Sopenharmony_ci .inversion = S5H1409_INVERSION_OFF, 55862306a36Sopenharmony_ci .status_mode = S5H1409_DEMODLOCKING, 55962306a36Sopenharmony_ci .mpeg_timing = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK, 56062306a36Sopenharmony_ci}; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic const struct s5h1409_config kworld_atsc_120_config = { 56362306a36Sopenharmony_ci .demod_address = 0x32 >> 1, 56462306a36Sopenharmony_ci .output_mode = S5H1409_SERIAL_OUTPUT, 56562306a36Sopenharmony_ci .gpio = S5H1409_GPIO_OFF, 56662306a36Sopenharmony_ci .inversion = S5H1409_INVERSION_OFF, 56762306a36Sopenharmony_ci .status_mode = S5H1409_DEMODLOCKING, 56862306a36Sopenharmony_ci .mpeg_timing = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK, 56962306a36Sopenharmony_ci}; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { 57262306a36Sopenharmony_ci .i2c_address = 0x64, 57362306a36Sopenharmony_ci .if_khz = 5380, 57462306a36Sopenharmony_ci}; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic const struct zl10353_config cx88_pinnacle_hybrid_pctv = { 57762306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 57862306a36Sopenharmony_ci .no_tuner = 1, 57962306a36Sopenharmony_ci .if2 = 45600, 58062306a36Sopenharmony_ci}; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic const struct zl10353_config cx88_geniatech_x8000_mt = { 58362306a36Sopenharmony_ci .demod_address = (0x1e >> 1), 58462306a36Sopenharmony_ci .no_tuner = 1, 58562306a36Sopenharmony_ci .disable_i2c_gate_ctrl = 1, 58662306a36Sopenharmony_ci}; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic const struct s5h1411_config dvico_fusionhdtv7_config = { 58962306a36Sopenharmony_ci .output_mode = S5H1411_SERIAL_OUTPUT, 59062306a36Sopenharmony_ci .gpio = S5H1411_GPIO_ON, 59162306a36Sopenharmony_ci .mpeg_timing = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK, 59262306a36Sopenharmony_ci .qam_if = S5H1411_IF_44000, 59362306a36Sopenharmony_ci .vsb_if = S5H1411_IF_44000, 59462306a36Sopenharmony_ci .inversion = S5H1411_INVERSION_OFF, 59562306a36Sopenharmony_ci .status_mode = S5H1411_DEMODLOCKING 59662306a36Sopenharmony_ci}; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic const struct xc5000_config dvico_fusionhdtv7_tuner_config = { 59962306a36Sopenharmony_ci .i2c_address = 0xc2 >> 1, 60062306a36Sopenharmony_ci .if_khz = 5380, 60162306a36Sopenharmony_ci}; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_cistatic int attach_xc3028(u8 addr, struct cx8802_dev *dev) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct dvb_frontend *fe; 60662306a36Sopenharmony_ci struct vb2_dvb_frontend *fe0 = NULL; 60762306a36Sopenharmony_ci struct xc2028_ctrl ctl; 60862306a36Sopenharmony_ci struct xc2028_config cfg = { 60962306a36Sopenharmony_ci .i2c_adap = &dev->core->i2c_adap, 61062306a36Sopenharmony_ci .i2c_addr = addr, 61162306a36Sopenharmony_ci .ctrl = &ctl, 61262306a36Sopenharmony_ci }; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* Get the first frontend */ 61562306a36Sopenharmony_ci fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); 61662306a36Sopenharmony_ci if (!fe0) 61762306a36Sopenharmony_ci return -EINVAL; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (!fe0->dvb.frontend) { 62062306a36Sopenharmony_ci pr_err("dvb frontend not attached. Can't attach xc3028\n"); 62162306a36Sopenharmony_ci return -EINVAL; 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci /* 62562306a36Sopenharmony_ci * Some xc3028 devices may be hidden by an I2C gate. This is known 62662306a36Sopenharmony_ci * to happen with some s5h1409-based devices. 62762306a36Sopenharmony_ci * Now that I2C gate is open, sets up xc3028 configuration 62862306a36Sopenharmony_ci */ 62962306a36Sopenharmony_ci cx88_setup_xc3028(dev->core, &ctl); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); 63262306a36Sopenharmony_ci if (!fe) { 63362306a36Sopenharmony_ci pr_err("xc3028 attach failed\n"); 63462306a36Sopenharmony_ci dvb_frontend_detach(fe0->dvb.frontend); 63562306a36Sopenharmony_ci dvb_unregister_frontend(fe0->dvb.frontend); 63662306a36Sopenharmony_ci fe0->dvb.frontend = NULL; 63762306a36Sopenharmony_ci return -EINVAL; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci pr_info("xc3028 attached\n"); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci return 0; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci struct dvb_frontend *fe; 64862306a36Sopenharmony_ci struct vb2_dvb_frontend *fe0 = NULL; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci /* Get the first frontend */ 65162306a36Sopenharmony_ci fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); 65262306a36Sopenharmony_ci if (!fe0) 65362306a36Sopenharmony_ci return -EINVAL; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (!fe0->dvb.frontend) { 65662306a36Sopenharmony_ci pr_err("dvb frontend not attached. Can't attach xc4000\n"); 65762306a36Sopenharmony_ci return -EINVAL; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap, 66162306a36Sopenharmony_ci cfg); 66262306a36Sopenharmony_ci if (!fe) { 66362306a36Sopenharmony_ci pr_err("xc4000 attach failed\n"); 66462306a36Sopenharmony_ci dvb_frontend_detach(fe0->dvb.frontend); 66562306a36Sopenharmony_ci dvb_unregister_frontend(fe0->dvb.frontend); 66662306a36Sopenharmony_ci fe0->dvb.frontend = NULL; 66762306a36Sopenharmony_ci return -EINVAL; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci pr_info("xc4000 attached\n"); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return 0; 67362306a36Sopenharmony_ci} 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic int cx24116_set_ts_param(struct dvb_frontend *fe, 67662306a36Sopenharmony_ci int is_punctured) 67762306a36Sopenharmony_ci{ 67862306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x2; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci return 0; 68362306a36Sopenharmony_ci} 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistatic int stv0900_set_ts_param(struct dvb_frontend *fe, 68662306a36Sopenharmony_ci int is_punctured) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci dev->ts_gen_cntrl = 0; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci return 0; 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic int cx24116_reset_device(struct dvb_frontend *fe) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 69862306a36Sopenharmony_ci struct cx88_core *core = dev->core; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* Reset the part */ 70162306a36Sopenharmony_ci /* Put the cx24116 into reset */ 70262306a36Sopenharmony_ci cx_write(MO_SRST_IO, 0); 70362306a36Sopenharmony_ci usleep_range(10000, 20000); 70462306a36Sopenharmony_ci /* Take the cx24116 out of reset */ 70562306a36Sopenharmony_ci cx_write(MO_SRST_IO, 1); 70662306a36Sopenharmony_ci usleep_range(10000, 20000); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci return 0; 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_cistatic const struct cx24116_config hauppauge_hvr4000_config = { 71262306a36Sopenharmony_ci .demod_address = 0x05, 71362306a36Sopenharmony_ci .set_ts_params = cx24116_set_ts_param, 71462306a36Sopenharmony_ci .reset_device = cx24116_reset_device, 71562306a36Sopenharmony_ci}; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic const struct cx24116_config tevii_s460_config = { 71862306a36Sopenharmony_ci .demod_address = 0x55, 71962306a36Sopenharmony_ci .set_ts_params = cx24116_set_ts_param, 72062306a36Sopenharmony_ci .reset_device = cx24116_reset_device, 72162306a36Sopenharmony_ci}; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_cistatic int ds3000_set_ts_param(struct dvb_frontend *fe, 72462306a36Sopenharmony_ci int is_punctured) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci dev->ts_gen_cntrl = 4; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci return 0; 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cistatic struct ds3000_config tevii_ds3000_config = { 73462306a36Sopenharmony_ci .demod_address = 0x68, 73562306a36Sopenharmony_ci .set_ts_params = ds3000_set_ts_param, 73662306a36Sopenharmony_ci}; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic struct ts2020_config tevii_ts2020_config = { 73962306a36Sopenharmony_ci .tuner_address = 0x60, 74062306a36Sopenharmony_ci .clk_out_div = 1, 74162306a36Sopenharmony_ci}; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic const struct stv0900_config prof_7301_stv0900_config = { 74462306a36Sopenharmony_ci .demod_address = 0x6a, 74562306a36Sopenharmony_ci/* demod_mode = 0,*/ 74662306a36Sopenharmony_ci .xtal = 27000000, 74762306a36Sopenharmony_ci .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ 74862306a36Sopenharmony_ci .diseqc_mode = 2,/* 2/3 PWM */ 74962306a36Sopenharmony_ci .tun1_maddress = 0,/* 0x60 */ 75062306a36Sopenharmony_ci .tun1_adc = 0,/* 2 Vpp */ 75162306a36Sopenharmony_ci .path1_mode = 3, 75262306a36Sopenharmony_ci .set_ts_params = stv0900_set_ts_param, 75362306a36Sopenharmony_ci}; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_cistatic const struct stb6100_config prof_7301_stb6100_config = { 75662306a36Sopenharmony_ci .tuner_address = 0x60, 75762306a36Sopenharmony_ci .refclock = 27000000, 75862306a36Sopenharmony_ci}; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic const struct stv0299_config tevii_tuner_sharp_config = { 76162306a36Sopenharmony_ci .demod_address = 0x68, 76262306a36Sopenharmony_ci .inittab = sharp_z0194a_inittab, 76362306a36Sopenharmony_ci .mclk = 88000000UL, 76462306a36Sopenharmony_ci .invert = 1, 76562306a36Sopenharmony_ci .skip_reinit = 0, 76662306a36Sopenharmony_ci .lock_output = 1, 76762306a36Sopenharmony_ci .volt13_op0_op1 = STV0299_VOLT13_OP1, 76862306a36Sopenharmony_ci .min_delay_ms = 100, 76962306a36Sopenharmony_ci .set_symbol_rate = sharp_z0194a_set_symbol_rate, 77062306a36Sopenharmony_ci .set_ts_params = cx24116_set_ts_param, 77162306a36Sopenharmony_ci}; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_cistatic const struct stv0288_config tevii_tuner_earda_config = { 77462306a36Sopenharmony_ci .demod_address = 0x68, 77562306a36Sopenharmony_ci .min_delay_ms = 100, 77662306a36Sopenharmony_ci .set_ts_params = cx24116_set_ts_param, 77762306a36Sopenharmony_ci}; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_cistatic int cx8802_alloc_frontends(struct cx8802_dev *dev) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci struct cx88_core *core = dev->core; 78262306a36Sopenharmony_ci struct vb2_dvb_frontend *fe = NULL; 78362306a36Sopenharmony_ci int i; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci mutex_init(&dev->frontends.lock); 78662306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->frontends.felist); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci if (!core->board.num_frontends) 78962306a36Sopenharmony_ci return -ENODEV; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci pr_info("%s: allocating %d frontend(s)\n", __func__, 79262306a36Sopenharmony_ci core->board.num_frontends); 79362306a36Sopenharmony_ci for (i = 1; i <= core->board.num_frontends; i++) { 79462306a36Sopenharmony_ci fe = vb2_dvb_alloc_frontend(&dev->frontends, i); 79562306a36Sopenharmony_ci if (!fe) { 79662306a36Sopenharmony_ci pr_err("%s() failed to alloc\n", __func__); 79762306a36Sopenharmony_ci vb2_dvb_dealloc_frontends(&dev->frontends); 79862306a36Sopenharmony_ci return -ENOMEM; 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci return 0; 80262306a36Sopenharmony_ci} 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cistatic const u8 samsung_smt_7020_inittab[] = { 80562306a36Sopenharmony_ci 0x01, 0x15, 80662306a36Sopenharmony_ci 0x02, 0x00, 80762306a36Sopenharmony_ci 0x03, 0x00, 80862306a36Sopenharmony_ci 0x04, 0x7D, 80962306a36Sopenharmony_ci 0x05, 0x0F, 81062306a36Sopenharmony_ci 0x06, 0x02, 81162306a36Sopenharmony_ci 0x07, 0x00, 81262306a36Sopenharmony_ci 0x08, 0x60, 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci 0x0A, 0xC2, 81562306a36Sopenharmony_ci 0x0B, 0x00, 81662306a36Sopenharmony_ci 0x0C, 0x01, 81762306a36Sopenharmony_ci 0x0D, 0x81, 81862306a36Sopenharmony_ci 0x0E, 0x44, 81962306a36Sopenharmony_ci 0x0F, 0x09, 82062306a36Sopenharmony_ci 0x10, 0x3C, 82162306a36Sopenharmony_ci 0x11, 0x84, 82262306a36Sopenharmony_ci 0x12, 0xDA, 82362306a36Sopenharmony_ci 0x13, 0x99, 82462306a36Sopenharmony_ci 0x14, 0x8D, 82562306a36Sopenharmony_ci 0x15, 0xCE, 82662306a36Sopenharmony_ci 0x16, 0xE8, 82762306a36Sopenharmony_ci 0x17, 0x43, 82862306a36Sopenharmony_ci 0x18, 0x1C, 82962306a36Sopenharmony_ci 0x19, 0x1B, 83062306a36Sopenharmony_ci 0x1A, 0x1D, 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci 0x1C, 0x12, 83362306a36Sopenharmony_ci 0x1D, 0x00, 83462306a36Sopenharmony_ci 0x1E, 0x00, 83562306a36Sopenharmony_ci 0x1F, 0x00, 83662306a36Sopenharmony_ci 0x20, 0x00, 83762306a36Sopenharmony_ci 0x21, 0x00, 83862306a36Sopenharmony_ci 0x22, 0x00, 83962306a36Sopenharmony_ci 0x23, 0x00, 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci 0x28, 0x02, 84262306a36Sopenharmony_ci 0x29, 0x28, 84362306a36Sopenharmony_ci 0x2A, 0x14, 84462306a36Sopenharmony_ci 0x2B, 0x0F, 84562306a36Sopenharmony_ci 0x2C, 0x09, 84662306a36Sopenharmony_ci 0x2D, 0x05, 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci 0x31, 0x1F, 84962306a36Sopenharmony_ci 0x32, 0x19, 85062306a36Sopenharmony_ci 0x33, 0xFC, 85162306a36Sopenharmony_ci 0x34, 0x13, 85262306a36Sopenharmony_ci 0xff, 0xff, 85362306a36Sopenharmony_ci}; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cistatic int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe) 85662306a36Sopenharmony_ci{ 85762306a36Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 85862306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 85962306a36Sopenharmony_ci u8 buf[4]; 86062306a36Sopenharmony_ci u32 div; 86162306a36Sopenharmony_ci struct i2c_msg msg = { 86262306a36Sopenharmony_ci .addr = 0x61, 86362306a36Sopenharmony_ci .flags = 0, 86462306a36Sopenharmony_ci .buf = buf, 86562306a36Sopenharmony_ci .len = sizeof(buf) }; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci div = c->frequency / 125; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci buf[0] = (div >> 8) & 0x7f; 87062306a36Sopenharmony_ci buf[1] = div & 0xff; 87162306a36Sopenharmony_ci buf[2] = 0x84; /* 0xC4 */ 87262306a36Sopenharmony_ci buf[3] = 0x00; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci if (c->frequency < 1500000) 87562306a36Sopenharmony_ci buf[3] |= 0x10; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 87862306a36Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1) 88162306a36Sopenharmony_ci return -EIO; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci return 0; 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cistatic int samsung_smt_7020_set_tone(struct dvb_frontend *fe, 88762306a36Sopenharmony_ci enum fe_sec_tone_mode tone) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 89062306a36Sopenharmony_ci struct cx88_core *core = dev->core; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x0800); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci switch (tone) { 89562306a36Sopenharmony_ci case SEC_TONE_ON: 89662306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x08); 89762306a36Sopenharmony_ci break; 89862306a36Sopenharmony_ci case SEC_TONE_OFF: 89962306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x08); 90062306a36Sopenharmony_ci break; 90162306a36Sopenharmony_ci default: 90262306a36Sopenharmony_ci return -EINVAL; 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci return 0; 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cistatic int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, 90962306a36Sopenharmony_ci enum fe_sec_voltage voltage) 91062306a36Sopenharmony_ci{ 91162306a36Sopenharmony_ci struct cx8802_dev *dev = fe->dvb->priv; 91262306a36Sopenharmony_ci struct cx88_core *core = dev->core; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci u8 data; 91562306a36Sopenharmony_ci struct i2c_msg msg = { 91662306a36Sopenharmony_ci .addr = 8, 91762306a36Sopenharmony_ci .flags = 0, 91862306a36Sopenharmony_ci .buf = &data, 91962306a36Sopenharmony_ci .len = sizeof(data) }; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x8000); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci switch (voltage) { 92462306a36Sopenharmony_ci case SEC_VOLTAGE_OFF: 92562306a36Sopenharmony_ci break; 92662306a36Sopenharmony_ci case SEC_VOLTAGE_13: 92762306a36Sopenharmony_ci data = ISL6421_EN1 | ISL6421_LLC1; 92862306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x80); 92962306a36Sopenharmony_ci break; 93062306a36Sopenharmony_ci case SEC_VOLTAGE_18: 93162306a36Sopenharmony_ci data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1; 93262306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x80); 93362306a36Sopenharmony_ci break; 93462306a36Sopenharmony_ci default: 93562306a36Sopenharmony_ci return -EINVAL; 93662306a36Sopenharmony_ci } 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; 93962306a36Sopenharmony_ci} 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_cistatic int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, 94262306a36Sopenharmony_ci u32 srate, u32 ratio) 94362306a36Sopenharmony_ci{ 94462306a36Sopenharmony_ci u8 aclk = 0; 94562306a36Sopenharmony_ci u8 bclk = 0; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci if (srate < 1500000) { 94862306a36Sopenharmony_ci aclk = 0xb7; 94962306a36Sopenharmony_ci bclk = 0x47; 95062306a36Sopenharmony_ci } else if (srate < 3000000) { 95162306a36Sopenharmony_ci aclk = 0xb7; 95262306a36Sopenharmony_ci bclk = 0x4b; 95362306a36Sopenharmony_ci } else if (srate < 7000000) { 95462306a36Sopenharmony_ci aclk = 0xb7; 95562306a36Sopenharmony_ci bclk = 0x4f; 95662306a36Sopenharmony_ci } else if (srate < 14000000) { 95762306a36Sopenharmony_ci aclk = 0xb7; 95862306a36Sopenharmony_ci bclk = 0x53; 95962306a36Sopenharmony_ci } else if (srate < 30000000) { 96062306a36Sopenharmony_ci aclk = 0xb6; 96162306a36Sopenharmony_ci bclk = 0x53; 96262306a36Sopenharmony_ci } else if (srate < 45000000) { 96362306a36Sopenharmony_ci aclk = 0xb4; 96462306a36Sopenharmony_ci bclk = 0x51; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci stv0299_writereg(fe, 0x13, aclk); 96862306a36Sopenharmony_ci stv0299_writereg(fe, 0x14, bclk); 96962306a36Sopenharmony_ci stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); 97062306a36Sopenharmony_ci stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); 97162306a36Sopenharmony_ci stv0299_writereg(fe, 0x21, ratio & 0xf0); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci return 0; 97462306a36Sopenharmony_ci} 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_cistatic const struct stv0299_config samsung_stv0299_config = { 97762306a36Sopenharmony_ci .demod_address = 0x68, 97862306a36Sopenharmony_ci .inittab = samsung_smt_7020_inittab, 97962306a36Sopenharmony_ci .mclk = 88000000UL, 98062306a36Sopenharmony_ci .invert = 0, 98162306a36Sopenharmony_ci .skip_reinit = 0, 98262306a36Sopenharmony_ci .lock_output = STV0299_LOCKOUTPUT_LK, 98362306a36Sopenharmony_ci .volt13_op0_op1 = STV0299_VOLT13_OP1, 98462306a36Sopenharmony_ci .min_delay_ms = 100, 98562306a36Sopenharmony_ci .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, 98662306a36Sopenharmony_ci}; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_cistatic int dvb_register(struct cx8802_dev *dev) 98962306a36Sopenharmony_ci{ 99062306a36Sopenharmony_ci struct cx88_core *core = dev->core; 99162306a36Sopenharmony_ci struct vb2_dvb_frontend *fe0, *fe1 = NULL; 99262306a36Sopenharmony_ci int mfe_shared = 0; /* bus not shared by default */ 99362306a36Sopenharmony_ci int res = -EINVAL; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci if (core->i2c_rc != 0) { 99662306a36Sopenharmony_ci pr_err("no i2c-bus available, cannot attach dvb drivers\n"); 99762306a36Sopenharmony_ci goto frontend_detach; 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* Get the first frontend */ 100162306a36Sopenharmony_ci fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); 100262306a36Sopenharmony_ci if (!fe0) 100362306a36Sopenharmony_ci goto frontend_detach; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci /* multi-frontend gate control is undefined or defaults to fe0 */ 100662306a36Sopenharmony_ci dev->frontends.gate = 0; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci /* Sets the gate control callback to be used by i2c command calls */ 100962306a36Sopenharmony_ci core->gate_ctrl = cx88_dvb_gate_ctrl; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* init frontend(s) */ 101262306a36Sopenharmony_ci switch (core->boardnr) { 101362306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_DVB_T1: 101462306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx22702_attach, 101562306a36Sopenharmony_ci &connexant_refboard_config, 101662306a36Sopenharmony_ci &core->i2c_adap); 101762306a36Sopenharmony_ci if (fe0->dvb.frontend) { 101862306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 101962306a36Sopenharmony_ci 0x61, &core->i2c_adap, 102062306a36Sopenharmony_ci DVB_PLL_THOMSON_DTT759X)) 102162306a36Sopenharmony_ci goto frontend_detach; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci break; 102462306a36Sopenharmony_ci case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: 102562306a36Sopenharmony_ci case CX88_BOARD_CONEXANT_DVB_T1: 102662306a36Sopenharmony_ci case CX88_BOARD_KWORLD_DVB_T_CX22702: 102762306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV1000: 102862306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx22702_attach, 102962306a36Sopenharmony_ci &connexant_refboard_config, 103062306a36Sopenharmony_ci &core->i2c_adap); 103162306a36Sopenharmony_ci if (fe0->dvb.frontend) { 103262306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 103362306a36Sopenharmony_ci 0x60, &core->i2c_adap, 103462306a36Sopenharmony_ci DVB_PLL_THOMSON_DTT7579)) 103562306a36Sopenharmony_ci goto frontend_detach; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci break; 103862306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV2000H: 103962306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR1100: 104062306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR1100LP: 104162306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR1300: 104262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx22702_attach, 104362306a36Sopenharmony_ci &hauppauge_hvr_config, 104462306a36Sopenharmony_ci &core->i2c_adap); 104562306a36Sopenharmony_ci if (fe0->dvb.frontend) { 104662306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 104762306a36Sopenharmony_ci &core->i2c_adap, 0x61, 104862306a36Sopenharmony_ci TUNER_PHILIPS_FMD1216ME_MK3)) 104962306a36Sopenharmony_ci goto frontend_detach; 105062306a36Sopenharmony_ci } 105162306a36Sopenharmony_ci break; 105262306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV2000H_J: 105362306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx22702_attach, 105462306a36Sopenharmony_ci &hauppauge_hvr_config, 105562306a36Sopenharmony_ci &core->i2c_adap); 105662306a36Sopenharmony_ci if (fe0->dvb.frontend) { 105762306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 105862306a36Sopenharmony_ci &core->i2c_adap, 0x61, 105962306a36Sopenharmony_ci TUNER_PHILIPS_FMD1216MEX_MK3)) 106062306a36Sopenharmony_ci goto frontend_detach; 106162306a36Sopenharmony_ci } 106262306a36Sopenharmony_ci break; 106362306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR3000: 106462306a36Sopenharmony_ci /* MFE frontend 1 */ 106562306a36Sopenharmony_ci mfe_shared = 1; 106662306a36Sopenharmony_ci dev->frontends.gate = 2; 106762306a36Sopenharmony_ci /* DVB-S init */ 106862306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24123_attach, 106962306a36Sopenharmony_ci &hauppauge_novas_config, 107062306a36Sopenharmony_ci &dev->core->i2c_adap); 107162306a36Sopenharmony_ci if (fe0->dvb.frontend) { 107262306a36Sopenharmony_ci if (!dvb_attach(isl6421_attach, 107362306a36Sopenharmony_ci fe0->dvb.frontend, 107462306a36Sopenharmony_ci &dev->core->i2c_adap, 107562306a36Sopenharmony_ci 0x08, ISL6421_DCL, 0x00, false)) 107662306a36Sopenharmony_ci goto frontend_detach; 107762306a36Sopenharmony_ci } 107862306a36Sopenharmony_ci /* MFE frontend 2 */ 107962306a36Sopenharmony_ci fe1 = vb2_dvb_get_frontend(&dev->frontends, 2); 108062306a36Sopenharmony_ci if (!fe1) 108162306a36Sopenharmony_ci goto frontend_detach; 108262306a36Sopenharmony_ci /* DVB-T init */ 108362306a36Sopenharmony_ci fe1->dvb.frontend = dvb_attach(cx22702_attach, 108462306a36Sopenharmony_ci &hauppauge_hvr_config, 108562306a36Sopenharmony_ci &dev->core->i2c_adap); 108662306a36Sopenharmony_ci if (fe1->dvb.frontend) { 108762306a36Sopenharmony_ci fe1->dvb.frontend->id = 1; 108862306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, 108962306a36Sopenharmony_ci fe1->dvb.frontend, 109062306a36Sopenharmony_ci &dev->core->i2c_adap, 109162306a36Sopenharmony_ci 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) 109262306a36Sopenharmony_ci goto frontend_detach; 109362306a36Sopenharmony_ci } 109462306a36Sopenharmony_ci break; 109562306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: 109662306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mt352_attach, 109762306a36Sopenharmony_ci &dvico_fusionhdtv, 109862306a36Sopenharmony_ci &core->i2c_adap); 109962306a36Sopenharmony_ci if (fe0->dvb.frontend) { 110062306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 110162306a36Sopenharmony_ci 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) 110262306a36Sopenharmony_ci goto frontend_detach; 110362306a36Sopenharmony_ci break; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci /* ZL10353 replaces MT352 on later cards */ 110662306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 110762306a36Sopenharmony_ci &dvico_fusionhdtv_plus_v1_1, 110862306a36Sopenharmony_ci &core->i2c_adap); 110962306a36Sopenharmony_ci if (fe0->dvb.frontend) { 111062306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 111162306a36Sopenharmony_ci 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) 111262306a36Sopenharmony_ci goto frontend_detach; 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci break; 111562306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: 111662306a36Sopenharmony_ci /* 111762306a36Sopenharmony_ci * The tin box says DEE1601, but it seems to be DTT7579 111862306a36Sopenharmony_ci * compatible, with a slightly different MT352 AGC gain. 111962306a36Sopenharmony_ci */ 112062306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mt352_attach, 112162306a36Sopenharmony_ci &dvico_fusionhdtv_dual, 112262306a36Sopenharmony_ci &core->i2c_adap); 112362306a36Sopenharmony_ci if (fe0->dvb.frontend) { 112462306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 112562306a36Sopenharmony_ci 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) 112662306a36Sopenharmony_ci goto frontend_detach; 112762306a36Sopenharmony_ci break; 112862306a36Sopenharmony_ci } 112962306a36Sopenharmony_ci /* ZL10353 replaces MT352 on later cards */ 113062306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 113162306a36Sopenharmony_ci &dvico_fusionhdtv_plus_v1_1, 113262306a36Sopenharmony_ci &core->i2c_adap); 113362306a36Sopenharmony_ci if (fe0->dvb.frontend) { 113462306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 113562306a36Sopenharmony_ci 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) 113662306a36Sopenharmony_ci goto frontend_detach; 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci break; 113962306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: 114062306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mt352_attach, 114162306a36Sopenharmony_ci &dvico_fusionhdtv, 114262306a36Sopenharmony_ci &core->i2c_adap); 114362306a36Sopenharmony_ci if (fe0->dvb.frontend) { 114462306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 114562306a36Sopenharmony_ci 0x61, NULL, DVB_PLL_LG_Z201)) 114662306a36Sopenharmony_ci goto frontend_detach; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci break; 114962306a36Sopenharmony_ci case CX88_BOARD_KWORLD_DVB_T: 115062306a36Sopenharmony_ci case CX88_BOARD_DNTV_LIVE_DVB_T: 115162306a36Sopenharmony_ci case CX88_BOARD_ADSTECH_DVB_T_PCI: 115262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mt352_attach, 115362306a36Sopenharmony_ci &dntv_live_dvbt_config, 115462306a36Sopenharmony_ci &core->i2c_adap); 115562306a36Sopenharmony_ci if (fe0->dvb.frontend) { 115662306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 115762306a36Sopenharmony_ci 0x61, NULL, DVB_PLL_UNKNOWN_1)) 115862306a36Sopenharmony_ci goto frontend_detach; 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci break; 116162306a36Sopenharmony_ci case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: 116262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) 116362306a36Sopenharmony_ci /* MT352 is on a secondary I2C bus made from some GPIO lines */ 116462306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mt352_attach, 116562306a36Sopenharmony_ci &dntv_live_dvbt_pro_config, 116662306a36Sopenharmony_ci &dev->vp3054->adap); 116762306a36Sopenharmony_ci if (fe0->dvb.frontend) { 116862306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 116962306a36Sopenharmony_ci &core->i2c_adap, 0x61, 117062306a36Sopenharmony_ci TUNER_PHILIPS_FMD1216ME_MK3)) 117162306a36Sopenharmony_ci goto frontend_detach; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci#else 117462306a36Sopenharmony_ci pr_err("built without vp3054 support\n"); 117562306a36Sopenharmony_ci#endif 117662306a36Sopenharmony_ci break; 117762306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: 117862306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 117962306a36Sopenharmony_ci &dvico_fusionhdtv_hybrid, 118062306a36Sopenharmony_ci &core->i2c_adap); 118162306a36Sopenharmony_ci if (fe0->dvb.frontend) { 118262306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 118362306a36Sopenharmony_ci &core->i2c_adap, 0x61, 118462306a36Sopenharmony_ci TUNER_THOMSON_FE6600)) 118562306a36Sopenharmony_ci goto frontend_detach; 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci break; 118862306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: 118962306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 119062306a36Sopenharmony_ci &dvico_fusionhdtv_xc3028, 119162306a36Sopenharmony_ci &core->i2c_adap); 119262306a36Sopenharmony_ci if (!fe0->dvb.frontend) 119362306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mt352_attach, 119462306a36Sopenharmony_ci &dvico_fusionhdtv_mt352_xc3028, 119562306a36Sopenharmony_ci &core->i2c_adap); 119662306a36Sopenharmony_ci /* 119762306a36Sopenharmony_ci * On this board, the demod provides the I2C bus pullup. 119862306a36Sopenharmony_ci * We must not permit gate_ctrl to be performed, or 119962306a36Sopenharmony_ci * the xc3028 cannot communicate on the bus. 120062306a36Sopenharmony_ci */ 120162306a36Sopenharmony_ci if (fe0->dvb.frontend) 120262306a36Sopenharmony_ci fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; 120362306a36Sopenharmony_ci if (attach_xc3028(0x61, dev) < 0) 120462306a36Sopenharmony_ci goto frontend_detach; 120562306a36Sopenharmony_ci break; 120662306a36Sopenharmony_ci case CX88_BOARD_PCHDTV_HD3000: 120762306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, 120862306a36Sopenharmony_ci &core->i2c_adap); 120962306a36Sopenharmony_ci if (fe0->dvb.frontend) { 121062306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 121162306a36Sopenharmony_ci &core->i2c_adap, 0x61, 121262306a36Sopenharmony_ci TUNER_THOMSON_DTT761X)) 121362306a36Sopenharmony_ci goto frontend_detach; 121462306a36Sopenharmony_ci } 121562306a36Sopenharmony_ci break; 121662306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: 121762306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x08; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci /* Do a hardware reset of chip before using it. */ 122062306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 1); 122162306a36Sopenharmony_ci msleep(100); 122262306a36Sopenharmony_ci cx_set(MO_GP0_IO, 1); 122362306a36Sopenharmony_ci msleep(200); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci /* Select RF connector callback */ 122662306a36Sopenharmony_ci fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; 122762306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(lgdt330x_attach, 122862306a36Sopenharmony_ci &fusionhdtv_3_gold, 122962306a36Sopenharmony_ci 0x0e, 123062306a36Sopenharmony_ci &core->i2c_adap); 123162306a36Sopenharmony_ci if (fe0->dvb.frontend) { 123262306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 123362306a36Sopenharmony_ci &core->i2c_adap, 0x61, 123462306a36Sopenharmony_ci TUNER_MICROTUNE_4042FI5)) 123562306a36Sopenharmony_ci goto frontend_detach; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci break; 123862306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: 123962306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x08; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci /* Do a hardware reset of chip before using it. */ 124262306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 1); 124362306a36Sopenharmony_ci msleep(100); 124462306a36Sopenharmony_ci cx_set(MO_GP0_IO, 9); 124562306a36Sopenharmony_ci msleep(200); 124662306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(lgdt330x_attach, 124762306a36Sopenharmony_ci &fusionhdtv_3_gold, 124862306a36Sopenharmony_ci 0x0e, 124962306a36Sopenharmony_ci &core->i2c_adap); 125062306a36Sopenharmony_ci if (fe0->dvb.frontend) { 125162306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 125262306a36Sopenharmony_ci &core->i2c_adap, 0x61, 125362306a36Sopenharmony_ci TUNER_THOMSON_DTT761X)) 125462306a36Sopenharmony_ci goto frontend_detach; 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci break; 125762306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: 125862306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x08; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci /* Do a hardware reset of chip before using it. */ 126162306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 1); 126262306a36Sopenharmony_ci msleep(100); 126362306a36Sopenharmony_ci cx_set(MO_GP0_IO, 1); 126462306a36Sopenharmony_ci msleep(200); 126562306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(lgdt330x_attach, 126662306a36Sopenharmony_ci &fusionhdtv_5_gold, 126762306a36Sopenharmony_ci 0x0e, 126862306a36Sopenharmony_ci &core->i2c_adap); 126962306a36Sopenharmony_ci if (fe0->dvb.frontend) { 127062306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 127162306a36Sopenharmony_ci &core->i2c_adap, 0x61, 127262306a36Sopenharmony_ci TUNER_LG_TDVS_H06XF)) 127362306a36Sopenharmony_ci goto frontend_detach; 127462306a36Sopenharmony_ci if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, 127562306a36Sopenharmony_ci &core->i2c_adap, 0x43)) 127662306a36Sopenharmony_ci goto frontend_detach; 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci break; 127962306a36Sopenharmony_ci case CX88_BOARD_PCHDTV_HD5500: 128062306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x08; 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci /* Do a hardware reset of chip before using it. */ 128362306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 1); 128462306a36Sopenharmony_ci msleep(100); 128562306a36Sopenharmony_ci cx_set(MO_GP0_IO, 1); 128662306a36Sopenharmony_ci msleep(200); 128762306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(lgdt330x_attach, 128862306a36Sopenharmony_ci &pchdtv_hd5500, 128962306a36Sopenharmony_ci 0x59, 129062306a36Sopenharmony_ci &core->i2c_adap); 129162306a36Sopenharmony_ci if (fe0->dvb.frontend) { 129262306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 129362306a36Sopenharmony_ci &core->i2c_adap, 0x61, 129462306a36Sopenharmony_ci TUNER_LG_TDVS_H06XF)) 129562306a36Sopenharmony_ci goto frontend_detach; 129662306a36Sopenharmony_ci if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, 129762306a36Sopenharmony_ci &core->i2c_adap, 0x43)) 129862306a36Sopenharmony_ci goto frontend_detach; 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci break; 130162306a36Sopenharmony_ci case CX88_BOARD_ATI_HDTVWONDER: 130262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(nxt200x_attach, 130362306a36Sopenharmony_ci &ati_hdtvwonder, 130462306a36Sopenharmony_ci &core->i2c_adap); 130562306a36Sopenharmony_ci if (fe0->dvb.frontend) { 130662306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, 130762306a36Sopenharmony_ci &core->i2c_adap, 0x61, 130862306a36Sopenharmony_ci TUNER_PHILIPS_TUV1236D)) 130962306a36Sopenharmony_ci goto frontend_detach; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci break; 131262306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: 131362306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: 131462306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24123_attach, 131562306a36Sopenharmony_ci &hauppauge_novas_config, 131662306a36Sopenharmony_ci &core->i2c_adap); 131762306a36Sopenharmony_ci if (fe0->dvb.frontend) { 131862306a36Sopenharmony_ci bool override_tone; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci if (core->model == 92001) 132162306a36Sopenharmony_ci override_tone = true; 132262306a36Sopenharmony_ci else 132362306a36Sopenharmony_ci override_tone = false; 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, 132662306a36Sopenharmony_ci &core->i2c_adap, 0x08, ISL6421_DCL, 132762306a36Sopenharmony_ci 0x00, override_tone)) 132862306a36Sopenharmony_ci goto frontend_detach; 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci break; 133162306a36Sopenharmony_ci case CX88_BOARD_KWORLD_DVBS_100: 133262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24123_attach, 133362306a36Sopenharmony_ci &kworld_dvbs_100_config, 133462306a36Sopenharmony_ci &core->i2c_adap); 133562306a36Sopenharmony_ci if (fe0->dvb.frontend) { 133662306a36Sopenharmony_ci core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; 133762306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci break; 134062306a36Sopenharmony_ci case CX88_BOARD_GENIATECH_DVBS: 134162306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24123_attach, 134262306a36Sopenharmony_ci &geniatech_dvbs_config, 134362306a36Sopenharmony_ci &core->i2c_adap); 134462306a36Sopenharmony_ci if (fe0->dvb.frontend) { 134562306a36Sopenharmony_ci core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; 134662306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; 134762306a36Sopenharmony_ci } 134862306a36Sopenharmony_ci break; 134962306a36Sopenharmony_ci case CX88_BOARD_PINNACLE_PCTV_HD_800i: 135062306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(s5h1409_attach, 135162306a36Sopenharmony_ci &pinnacle_pctv_hd_800i_config, 135262306a36Sopenharmony_ci &core->i2c_adap); 135362306a36Sopenharmony_ci if (fe0->dvb.frontend) { 135462306a36Sopenharmony_ci if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, 135562306a36Sopenharmony_ci &core->i2c_adap, 135662306a36Sopenharmony_ci &pinnacle_pctv_hd_800i_tuner_config)) 135762306a36Sopenharmony_ci goto frontend_detach; 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci break; 136062306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: 136162306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(s5h1409_attach, 136262306a36Sopenharmony_ci &dvico_hdtv5_pci_nano_config, 136362306a36Sopenharmony_ci &core->i2c_adap); 136462306a36Sopenharmony_ci if (fe0->dvb.frontend) { 136562306a36Sopenharmony_ci struct dvb_frontend *fe; 136662306a36Sopenharmony_ci struct xc2028_config cfg = { 136762306a36Sopenharmony_ci .i2c_adap = &core->i2c_adap, 136862306a36Sopenharmony_ci .i2c_addr = 0x61, 136962306a36Sopenharmony_ci }; 137062306a36Sopenharmony_ci static struct xc2028_ctrl ctl = { 137162306a36Sopenharmony_ci .fname = XC2028_DEFAULT_FIRMWARE, 137262306a36Sopenharmony_ci .max_len = 64, 137362306a36Sopenharmony_ci .scode_table = XC3028_FE_OREN538, 137462306a36Sopenharmony_ci }; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci fe = dvb_attach(xc2028_attach, 137762306a36Sopenharmony_ci fe0->dvb.frontend, &cfg); 137862306a36Sopenharmony_ci if (fe && fe->ops.tuner_ops.set_config) 137962306a36Sopenharmony_ci fe->ops.tuner_ops.set_config(fe, &ctl); 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci break; 138262306a36Sopenharmony_ci case CX88_BOARD_NOTONLYTV_LV3H: 138362306a36Sopenharmony_ci case CX88_BOARD_PINNACLE_HYBRID_PCTV: 138462306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV1800H: 138562306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 138662306a36Sopenharmony_ci &cx88_pinnacle_hybrid_pctv, 138762306a36Sopenharmony_ci &core->i2c_adap); 138862306a36Sopenharmony_ci if (fe0->dvb.frontend) { 138962306a36Sopenharmony_ci fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; 139062306a36Sopenharmony_ci if (attach_xc3028(0x61, dev) < 0) 139162306a36Sopenharmony_ci goto frontend_detach; 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci break; 139462306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV1800H_XC4000: 139562306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV2000H_PLUS: 139662306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 139762306a36Sopenharmony_ci &cx88_pinnacle_hybrid_pctv, 139862306a36Sopenharmony_ci &core->i2c_adap); 139962306a36Sopenharmony_ci if (fe0->dvb.frontend) { 140062306a36Sopenharmony_ci struct xc4000_config cfg = { 140162306a36Sopenharmony_ci .i2c_address = 0x61, 140262306a36Sopenharmony_ci .default_pm = 0, 140362306a36Sopenharmony_ci .dvb_amplitude = 134, 140462306a36Sopenharmony_ci .set_smoothedcvbs = 1, 140562306a36Sopenharmony_ci .if_khz = 4560 140662306a36Sopenharmony_ci }; 140762306a36Sopenharmony_ci fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; 140862306a36Sopenharmony_ci if (attach_xc4000(dev, &cfg) < 0) 140962306a36Sopenharmony_ci goto frontend_detach; 141062306a36Sopenharmony_ci } 141162306a36Sopenharmony_ci break; 141262306a36Sopenharmony_ci case CX88_BOARD_GENIATECH_X8000_MT: 141362306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x00; 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 141662306a36Sopenharmony_ci &cx88_geniatech_x8000_mt, 141762306a36Sopenharmony_ci &core->i2c_adap); 141862306a36Sopenharmony_ci if (attach_xc3028(0x61, dev) < 0) 141962306a36Sopenharmony_ci goto frontend_detach; 142062306a36Sopenharmony_ci break; 142162306a36Sopenharmony_ci case CX88_BOARD_KWORLD_ATSC_120: 142262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(s5h1409_attach, 142362306a36Sopenharmony_ci &kworld_atsc_120_config, 142462306a36Sopenharmony_ci &core->i2c_adap); 142562306a36Sopenharmony_ci if (attach_xc3028(0x61, dev) < 0) 142662306a36Sopenharmony_ci goto frontend_detach; 142762306a36Sopenharmony_ci break; 142862306a36Sopenharmony_ci case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: 142962306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(s5h1411_attach, 143062306a36Sopenharmony_ci &dvico_fusionhdtv7_config, 143162306a36Sopenharmony_ci &core->i2c_adap); 143262306a36Sopenharmony_ci if (fe0->dvb.frontend) { 143362306a36Sopenharmony_ci if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, 143462306a36Sopenharmony_ci &core->i2c_adap, 143562306a36Sopenharmony_ci &dvico_fusionhdtv7_tuner_config)) 143662306a36Sopenharmony_ci goto frontend_detach; 143762306a36Sopenharmony_ci } 143862306a36Sopenharmony_ci break; 143962306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR4000: 144062306a36Sopenharmony_ci /* MFE frontend 1 */ 144162306a36Sopenharmony_ci mfe_shared = 1; 144262306a36Sopenharmony_ci dev->frontends.gate = 2; 144362306a36Sopenharmony_ci /* DVB-S/S2 Init */ 144462306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24116_attach, 144562306a36Sopenharmony_ci &hauppauge_hvr4000_config, 144662306a36Sopenharmony_ci &dev->core->i2c_adap); 144762306a36Sopenharmony_ci if (fe0->dvb.frontend) { 144862306a36Sopenharmony_ci if (!dvb_attach(isl6421_attach, 144962306a36Sopenharmony_ci fe0->dvb.frontend, 145062306a36Sopenharmony_ci &dev->core->i2c_adap, 145162306a36Sopenharmony_ci 0x08, ISL6421_DCL, 0x00, false)) 145262306a36Sopenharmony_ci goto frontend_detach; 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci /* MFE frontend 2 */ 145562306a36Sopenharmony_ci fe1 = vb2_dvb_get_frontend(&dev->frontends, 2); 145662306a36Sopenharmony_ci if (!fe1) 145762306a36Sopenharmony_ci goto frontend_detach; 145862306a36Sopenharmony_ci /* DVB-T Init */ 145962306a36Sopenharmony_ci fe1->dvb.frontend = dvb_attach(cx22702_attach, 146062306a36Sopenharmony_ci &hauppauge_hvr_config, 146162306a36Sopenharmony_ci &dev->core->i2c_adap); 146262306a36Sopenharmony_ci if (fe1->dvb.frontend) { 146362306a36Sopenharmony_ci fe1->dvb.frontend->id = 1; 146462306a36Sopenharmony_ci if (!dvb_attach(simple_tuner_attach, 146562306a36Sopenharmony_ci fe1->dvb.frontend, 146662306a36Sopenharmony_ci &dev->core->i2c_adap, 146762306a36Sopenharmony_ci 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) 146862306a36Sopenharmony_ci goto frontend_detach; 146962306a36Sopenharmony_ci } 147062306a36Sopenharmony_ci break; 147162306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR4000LITE: 147262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24116_attach, 147362306a36Sopenharmony_ci &hauppauge_hvr4000_config, 147462306a36Sopenharmony_ci &dev->core->i2c_adap); 147562306a36Sopenharmony_ci if (fe0->dvb.frontend) { 147662306a36Sopenharmony_ci if (!dvb_attach(isl6421_attach, 147762306a36Sopenharmony_ci fe0->dvb.frontend, 147862306a36Sopenharmony_ci &dev->core->i2c_adap, 147962306a36Sopenharmony_ci 0x08, ISL6421_DCL, 0x00, false)) 148062306a36Sopenharmony_ci goto frontend_detach; 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci break; 148362306a36Sopenharmony_ci case CX88_BOARD_PROF_6200: 148462306a36Sopenharmony_ci case CX88_BOARD_TBS_8910: 148562306a36Sopenharmony_ci case CX88_BOARD_TEVII_S420: 148662306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(stv0299_attach, 148762306a36Sopenharmony_ci &tevii_tuner_sharp_config, 148862306a36Sopenharmony_ci &core->i2c_adap); 148962306a36Sopenharmony_ci if (fe0->dvb.frontend) { 149062306a36Sopenharmony_ci if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, 149162306a36Sopenharmony_ci &core->i2c_adap, DVB_PLL_OPERA1)) 149262306a36Sopenharmony_ci goto frontend_detach; 149362306a36Sopenharmony_ci core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; 149462306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci } else { 149762306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(stv0288_attach, 149862306a36Sopenharmony_ci &tevii_tuner_earda_config, 149962306a36Sopenharmony_ci &core->i2c_adap); 150062306a36Sopenharmony_ci if (fe0->dvb.frontend) { 150162306a36Sopenharmony_ci if (!dvb_attach(stb6000_attach, 150262306a36Sopenharmony_ci fe0->dvb.frontend, 0x61, 150362306a36Sopenharmony_ci &core->i2c_adap)) 150462306a36Sopenharmony_ci goto frontend_detach; 150562306a36Sopenharmony_ci core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; 150662306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; 150762306a36Sopenharmony_ci } 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci break; 151062306a36Sopenharmony_ci case CX88_BOARD_TEVII_S460: 151162306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24116_attach, 151262306a36Sopenharmony_ci &tevii_s460_config, 151362306a36Sopenharmony_ci &core->i2c_adap); 151462306a36Sopenharmony_ci if (fe0->dvb.frontend) 151562306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; 151662306a36Sopenharmony_ci break; 151762306a36Sopenharmony_ci case CX88_BOARD_TEVII_S464: 151862306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(ds3000_attach, 151962306a36Sopenharmony_ci &tevii_ds3000_config, 152062306a36Sopenharmony_ci &core->i2c_adap); 152162306a36Sopenharmony_ci if (fe0->dvb.frontend) { 152262306a36Sopenharmony_ci dvb_attach(ts2020_attach, fe0->dvb.frontend, 152362306a36Sopenharmony_ci &tevii_ts2020_config, &core->i2c_adap); 152462306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = 152562306a36Sopenharmony_ci tevii_dvbs_set_voltage; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci break; 152862306a36Sopenharmony_ci case CX88_BOARD_OMICOM_SS4_PCI: 152962306a36Sopenharmony_ci case CX88_BOARD_TBS_8920: 153062306a36Sopenharmony_ci case CX88_BOARD_PROF_7300: 153162306a36Sopenharmony_ci case CX88_BOARD_SATTRADE_ST4200: 153262306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(cx24116_attach, 153362306a36Sopenharmony_ci &hauppauge_hvr4000_config, 153462306a36Sopenharmony_ci &core->i2c_adap); 153562306a36Sopenharmony_ci if (fe0->dvb.frontend) 153662306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; 153762306a36Sopenharmony_ci break; 153862306a36Sopenharmony_ci case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: 153962306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(zl10353_attach, 154062306a36Sopenharmony_ci &cx88_terratec_cinergy_ht_pci_mkii_config, 154162306a36Sopenharmony_ci &core->i2c_adap); 154262306a36Sopenharmony_ci if (fe0->dvb.frontend) { 154362306a36Sopenharmony_ci fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; 154462306a36Sopenharmony_ci if (attach_xc3028(0x61, dev) < 0) 154562306a36Sopenharmony_ci goto frontend_detach; 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci break; 154862306a36Sopenharmony_ci case CX88_BOARD_PROF_7301:{ 154962306a36Sopenharmony_ci struct dvb_tuner_ops *tuner_ops = NULL; 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(stv0900_attach, 155262306a36Sopenharmony_ci &prof_7301_stv0900_config, 155362306a36Sopenharmony_ci &core->i2c_adap, 0); 155462306a36Sopenharmony_ci if (fe0->dvb.frontend) { 155562306a36Sopenharmony_ci if (!dvb_attach(stb6100_attach, fe0->dvb.frontend, 155662306a36Sopenharmony_ci &prof_7301_stb6100_config, 155762306a36Sopenharmony_ci &core->i2c_adap)) 155862306a36Sopenharmony_ci goto frontend_detach; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci tuner_ops = &fe0->dvb.frontend->ops.tuner_ops; 156162306a36Sopenharmony_ci tuner_ops->set_frequency = stb6100_set_freq; 156262306a36Sopenharmony_ci tuner_ops->get_frequency = stb6100_get_freq; 156362306a36Sopenharmony_ci tuner_ops->set_bandwidth = stb6100_set_bandw; 156462306a36Sopenharmony_ci tuner_ops->get_bandwidth = stb6100_get_bandw; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci core->prev_set_voltage = 156762306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage; 156862306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = 156962306a36Sopenharmony_ci tevii_dvbs_set_voltage; 157062306a36Sopenharmony_ci } 157162306a36Sopenharmony_ci break; 157262306a36Sopenharmony_ci } 157362306a36Sopenharmony_ci case CX88_BOARD_SAMSUNG_SMT_7020: 157462306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x08; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x0101); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x01); 157962306a36Sopenharmony_ci msleep(100); 158062306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x01); 158162306a36Sopenharmony_ci msleep(200); 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(stv0299_attach, 158462306a36Sopenharmony_ci &samsung_stv0299_config, 158562306a36Sopenharmony_ci &dev->core->i2c_adap); 158662306a36Sopenharmony_ci if (fe0->dvb.frontend) { 158762306a36Sopenharmony_ci fe0->dvb.frontend->ops.tuner_ops.set_params = 158862306a36Sopenharmony_ci samsung_smt_7020_tuner_set_params; 158962306a36Sopenharmony_ci fe0->dvb.frontend->tuner_priv = 159062306a36Sopenharmony_ci &dev->core->i2c_adap; 159162306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = 159262306a36Sopenharmony_ci samsung_smt_7020_set_voltage; 159362306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_tone = 159462306a36Sopenharmony_ci samsung_smt_7020_set_tone; 159562306a36Sopenharmony_ci } 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci break; 159862306a36Sopenharmony_ci case CX88_BOARD_TWINHAN_VP1027_DVBS: 159962306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x00; 160062306a36Sopenharmony_ci fe0->dvb.frontend = dvb_attach(mb86a16_attach, 160162306a36Sopenharmony_ci &twinhan_vp1027, 160262306a36Sopenharmony_ci &core->i2c_adap); 160362306a36Sopenharmony_ci if (fe0->dvb.frontend) { 160462306a36Sopenharmony_ci core->prev_set_voltage = 160562306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage; 160662306a36Sopenharmony_ci fe0->dvb.frontend->ops.set_voltage = 160762306a36Sopenharmony_ci vp1027_set_voltage; 160862306a36Sopenharmony_ci } 160962306a36Sopenharmony_ci break; 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci default: 161262306a36Sopenharmony_ci pr_err("The frontend of your DVB/ATSC card isn't supported yet\n"); 161362306a36Sopenharmony_ci break; 161462306a36Sopenharmony_ci } 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) { 161762306a36Sopenharmony_ci pr_err("frontend initialization failed\n"); 161862306a36Sopenharmony_ci goto frontend_detach; 161962306a36Sopenharmony_ci } 162062306a36Sopenharmony_ci /* define general-purpose callback pointer */ 162162306a36Sopenharmony_ci fe0->dvb.frontend->callback = cx88_tuner_callback; 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci /* Ensure all frontends negotiate bus access */ 162462306a36Sopenharmony_ci fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; 162562306a36Sopenharmony_ci if (fe1) 162662306a36Sopenharmony_ci fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci /* Put the tuner in standby to keep it quiet */ 162962306a36Sopenharmony_ci call_all(core, tuner, standby); 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci /* register everything */ 163262306a36Sopenharmony_ci res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, 163362306a36Sopenharmony_ci &dev->pci->dev, NULL, adapter_nr, 163462306a36Sopenharmony_ci mfe_shared); 163562306a36Sopenharmony_ci if (res) 163662306a36Sopenharmony_ci goto frontend_detach; 163762306a36Sopenharmony_ci return res; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cifrontend_detach: 164062306a36Sopenharmony_ci core->gate_ctrl = NULL; 164162306a36Sopenharmony_ci vb2_dvb_dealloc_frontends(&dev->frontends); 164262306a36Sopenharmony_ci return res; 164362306a36Sopenharmony_ci} 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci/* CX8802 MPEG -> mini driver - We have been given the hardware */ 164862306a36Sopenharmony_cistatic int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) 164962306a36Sopenharmony_ci{ 165062306a36Sopenharmony_ci struct cx88_core *core = drv->core; 165162306a36Sopenharmony_ci int err = 0; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci dprintk(1, "%s\n", __func__); 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci switch (core->boardnr) { 165662306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR1300: 165762306a36Sopenharmony_ci /* We arrive here with either the cx23416 or the cx22702 165862306a36Sopenharmony_ci * on the bus. Take the bus from the cx23416 and enable the 165962306a36Sopenharmony_ci * cx22702 demod 166062306a36Sopenharmony_ci */ 166162306a36Sopenharmony_ci /* Toggle reset on cx22702 leaving i2c active */ 166262306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x00000080); 166362306a36Sopenharmony_ci udelay(1000); 166462306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x00000080); 166562306a36Sopenharmony_ci udelay(50); 166662306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x00000080); 166762306a36Sopenharmony_ci udelay(1000); 166862306a36Sopenharmony_ci /* enable the cx22702 pins */ 166962306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x00000004); 167062306a36Sopenharmony_ci udelay(1000); 167162306a36Sopenharmony_ci break; 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR3000: 167462306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR4000: 167562306a36Sopenharmony_ci /* Toggle reset on cx22702 leaving i2c active */ 167662306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x00000080); 167762306a36Sopenharmony_ci udelay(1000); 167862306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x00000080); 167962306a36Sopenharmony_ci udelay(50); 168062306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x00000080); 168162306a36Sopenharmony_ci udelay(1000); 168262306a36Sopenharmony_ci switch (core->dvbdev->frontends.active_fe_id) { 168362306a36Sopenharmony_ci case 1: /* DVB-S/S2 Enabled */ 168462306a36Sopenharmony_ci /* tri-state the cx22702 pins */ 168562306a36Sopenharmony_ci cx_set(MO_GP0_IO, 0x00000004); 168662306a36Sopenharmony_ci /* Take the cx24116/cx24123 out of reset */ 168762306a36Sopenharmony_ci cx_write(MO_SRST_IO, 1); 168862306a36Sopenharmony_ci core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ 168962306a36Sopenharmony_ci break; 169062306a36Sopenharmony_ci case 2: /* DVB-T Enabled */ 169162306a36Sopenharmony_ci /* Put the cx24116/cx24123 into reset */ 169262306a36Sopenharmony_ci cx_write(MO_SRST_IO, 0); 169362306a36Sopenharmony_ci /* enable the cx22702 pins */ 169462306a36Sopenharmony_ci cx_clear(MO_GP0_IO, 0x00000004); 169562306a36Sopenharmony_ci core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ 169662306a36Sopenharmony_ci break; 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci udelay(1000); 169962306a36Sopenharmony_ci break; 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci case CX88_BOARD_WINFAST_DTV2000H_PLUS: 170262306a36Sopenharmony_ci /* set RF input to AIR for DVB-T (GPIO 16) */ 170362306a36Sopenharmony_ci cx_write(MO_GP2_IO, 0x0101); 170462306a36Sopenharmony_ci break; 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci default: 170762306a36Sopenharmony_ci err = -ENODEV; 170862306a36Sopenharmony_ci } 170962306a36Sopenharmony_ci return err; 171062306a36Sopenharmony_ci} 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci/* CX8802 MPEG -> mini driver - We no longer have the hardware */ 171362306a36Sopenharmony_cistatic int cx8802_dvb_advise_release(struct cx8802_driver *drv) 171462306a36Sopenharmony_ci{ 171562306a36Sopenharmony_ci struct cx88_core *core = drv->core; 171662306a36Sopenharmony_ci int err = 0; 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci dprintk(1, "%s\n", __func__); 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci switch (core->boardnr) { 172162306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR1300: 172262306a36Sopenharmony_ci /* Do Nothing, leave the cx22702 on the bus. */ 172362306a36Sopenharmony_ci break; 172462306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR3000: 172562306a36Sopenharmony_ci case CX88_BOARD_HAUPPAUGE_HVR4000: 172662306a36Sopenharmony_ci break; 172762306a36Sopenharmony_ci default: 172862306a36Sopenharmony_ci err = -ENODEV; 172962306a36Sopenharmony_ci } 173062306a36Sopenharmony_ci return err; 173162306a36Sopenharmony_ci} 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_cistatic int cx8802_dvb_probe(struct cx8802_driver *drv) 173462306a36Sopenharmony_ci{ 173562306a36Sopenharmony_ci struct cx88_core *core = drv->core; 173662306a36Sopenharmony_ci struct cx8802_dev *dev = drv->core->dvbdev; 173762306a36Sopenharmony_ci int err; 173862306a36Sopenharmony_ci struct vb2_dvb_frontend *fe; 173962306a36Sopenharmony_ci int i; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci dprintk(1, "%s\n", __func__); 174262306a36Sopenharmony_ci dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", 174362306a36Sopenharmony_ci core->boardnr, 174462306a36Sopenharmony_ci core->name, 174562306a36Sopenharmony_ci core->pci_bus, 174662306a36Sopenharmony_ci core->pci_slot); 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci err = -ENODEV; 174962306a36Sopenharmony_ci if (!(core->board.mpeg & CX88_MPEG_DVB)) 175062306a36Sopenharmony_ci goto fail_core; 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci /* If vp3054 isn't enabled, a stub will just return 0 */ 175362306a36Sopenharmony_ci err = vp3054_i2c_probe(dev); 175462306a36Sopenharmony_ci if (err != 0) 175562306a36Sopenharmony_ci goto fail_core; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci /* dvb stuff */ 175862306a36Sopenharmony_ci pr_info("cx2388x based DVB/ATSC card\n"); 175962306a36Sopenharmony_ci dev->ts_gen_cntrl = 0x0c; 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci err = cx8802_alloc_frontends(dev); 176262306a36Sopenharmony_ci if (err) 176362306a36Sopenharmony_ci goto fail_core; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci for (i = 1; i <= core->board.num_frontends; i++) { 176662306a36Sopenharmony_ci struct vb2_queue *q; 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i); 176962306a36Sopenharmony_ci if (!fe) { 177062306a36Sopenharmony_ci pr_err("%s() failed to get frontend(%d)\n", 177162306a36Sopenharmony_ci __func__, i); 177262306a36Sopenharmony_ci err = -ENODEV; 177362306a36Sopenharmony_ci goto fail_probe; 177462306a36Sopenharmony_ci } 177562306a36Sopenharmony_ci q = &fe->dvb.dvbq; 177662306a36Sopenharmony_ci q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 177762306a36Sopenharmony_ci q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; 177862306a36Sopenharmony_ci q->gfp_flags = GFP_DMA32; 177962306a36Sopenharmony_ci q->min_buffers_needed = 2; 178062306a36Sopenharmony_ci q->drv_priv = dev; 178162306a36Sopenharmony_ci q->buf_struct_size = sizeof(struct cx88_buffer); 178262306a36Sopenharmony_ci q->ops = &dvb_qops; 178362306a36Sopenharmony_ci q->mem_ops = &vb2_dma_sg_memops; 178462306a36Sopenharmony_ci q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 178562306a36Sopenharmony_ci q->lock = &core->lock; 178662306a36Sopenharmony_ci q->dev = &dev->pci->dev; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci err = vb2_queue_init(q); 178962306a36Sopenharmony_ci if (err < 0) 179062306a36Sopenharmony_ci goto fail_probe; 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci /* init struct vb2_dvb */ 179362306a36Sopenharmony_ci fe->dvb.name = dev->core->name; 179462306a36Sopenharmony_ci } 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci err = dvb_register(dev); 179762306a36Sopenharmony_ci if (err) 179862306a36Sopenharmony_ci /* frontends/adapter de-allocated in dvb_register */ 179962306a36Sopenharmony_ci pr_err("dvb_register failed (err = %d)\n", err); 180062306a36Sopenharmony_ci return err; 180162306a36Sopenharmony_cifail_probe: 180262306a36Sopenharmony_ci vb2_dvb_dealloc_frontends(&core->dvbdev->frontends); 180362306a36Sopenharmony_cifail_core: 180462306a36Sopenharmony_ci return err; 180562306a36Sopenharmony_ci} 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_cistatic int cx8802_dvb_remove(struct cx8802_driver *drv) 180862306a36Sopenharmony_ci{ 180962306a36Sopenharmony_ci struct cx88_core *core = drv->core; 181062306a36Sopenharmony_ci struct cx8802_dev *dev = drv->core->dvbdev; 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci dprintk(1, "%s\n", __func__); 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci vb2_dvb_unregister_bus(&dev->frontends); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci vp3054_i2c_remove(dev); 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci core->gate_ctrl = NULL; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci return 0; 182162306a36Sopenharmony_ci} 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_cistatic struct cx8802_driver cx8802_dvb_driver = { 182462306a36Sopenharmony_ci .type_id = CX88_MPEG_DVB, 182562306a36Sopenharmony_ci .hw_access = CX8802_DRVCTL_SHARED, 182662306a36Sopenharmony_ci .probe = cx8802_dvb_probe, 182762306a36Sopenharmony_ci .remove = cx8802_dvb_remove, 182862306a36Sopenharmony_ci .advise_acquire = cx8802_dvb_advise_acquire, 182962306a36Sopenharmony_ci .advise_release = cx8802_dvb_advise_release, 183062306a36Sopenharmony_ci}; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_cistatic int __init dvb_init(void) 183362306a36Sopenharmony_ci{ 183462306a36Sopenharmony_ci pr_info("cx2388x dvb driver version %s loaded\n", CX88_VERSION); 183562306a36Sopenharmony_ci return cx8802_register_driver(&cx8802_dvb_driver); 183662306a36Sopenharmony_ci} 183762306a36Sopenharmony_ci 183862306a36Sopenharmony_cistatic void __exit dvb_fini(void) 183962306a36Sopenharmony_ci{ 184062306a36Sopenharmony_ci cx8802_unregister_driver(&cx8802_dvb_driver); 184162306a36Sopenharmony_ci} 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_cimodule_init(dvb_init); 184462306a36Sopenharmony_cimodule_exit(dvb_fini); 1845