1*c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24c66c920SMichael Krufky /*
34c66c920SMichael Krufky * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
44c66c920SMichael Krufky *
508e10972SMichael Krufky * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
64c66c920SMichael Krufky */
74c66c920SMichael Krufky
84c66c920SMichael Krufky #include "mxl111sf-tuner.h"
94c66c920SMichael Krufky #include "mxl111sf-phy.h"
104c66c920SMichael Krufky #include "mxl111sf-reg.h"
114c66c920SMichael Krufky
124c66c920SMichael Krufky /* debug */
134c66c920SMichael Krufky static int mxl111sf_tuner_debug;
144c66c920SMichael Krufky module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
154c66c920SMichael Krufky MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
164c66c920SMichael Krufky
174c66c920SMichael Krufky #define mxl_dbg(fmt, arg...) \
184c66c920SMichael Krufky if (mxl111sf_tuner_debug) \
194c66c920SMichael Krufky mxl_printk(KERN_DEBUG, fmt, ##arg)
204c66c920SMichael Krufky
214c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
224c66c920SMichael Krufky
234c66c920SMichael Krufky struct mxl111sf_tuner_state {
244c66c920SMichael Krufky struct mxl111sf_state *mxl_state;
254c66c920SMichael Krufky
2640205163SJulia Lawall const struct mxl111sf_tuner_config *cfg;
274c66c920SMichael Krufky
28f7901f9bSMichael Krufky enum mxl_if_freq if_freq;
29f7901f9bSMichael Krufky
304c66c920SMichael Krufky u32 frequency;
314c66c920SMichael Krufky u32 bandwidth;
324c66c920SMichael Krufky };
334c66c920SMichael Krufky
mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state * state,u8 addr,u8 * data)344c66c920SMichael Krufky static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
354c66c920SMichael Krufky u8 addr, u8 *data)
364c66c920SMichael Krufky {
374c66c920SMichael Krufky return (state->cfg->read_reg) ?
384c66c920SMichael Krufky state->cfg->read_reg(state->mxl_state, addr, data) :
394c66c920SMichael Krufky -EINVAL;
404c66c920SMichael Krufky }
414c66c920SMichael Krufky
mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state * state,u8 addr,u8 data)424c66c920SMichael Krufky static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
434c66c920SMichael Krufky u8 addr, u8 data)
444c66c920SMichael Krufky {
454c66c920SMichael Krufky return (state->cfg->write_reg) ?
464c66c920SMichael Krufky state->cfg->write_reg(state->mxl_state, addr, data) :
474c66c920SMichael Krufky -EINVAL;
484c66c920SMichael Krufky }
494c66c920SMichael Krufky
mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state * state,struct mxl111sf_reg_ctrl_info * ctrl_reg_info)504c66c920SMichael Krufky static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
514c66c920SMichael Krufky struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
524c66c920SMichael Krufky {
534c66c920SMichael Krufky return (state->cfg->program_regs) ?
544c66c920SMichael Krufky state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
554c66c920SMichael Krufky -EINVAL;
564c66c920SMichael Krufky }
574c66c920SMichael Krufky
mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state * state,int onoff)584c66c920SMichael Krufky static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
594c66c920SMichael Krufky int onoff)
604c66c920SMichael Krufky {
614c66c920SMichael Krufky return (state->cfg->top_master_ctrl) ?
624c66c920SMichael Krufky state->cfg->top_master_ctrl(state->mxl_state, onoff) :
634c66c920SMichael Krufky -EINVAL;
644c66c920SMichael Krufky }
654c66c920SMichael Krufky
664c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
674c66c920SMichael Krufky
684c66c920SMichael Krufky static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
694c66c920SMichael Krufky {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
704c66c920SMichael Krufky DIG_MODEINDEX, _A, _CSF, */
714c66c920SMichael Krufky {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
724c66c920SMichael Krufky {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
734c66c920SMichael Krufky {0, 0, 0}
744c66c920SMichael Krufky };
754c66c920SMichael Krufky
764c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
774c66c920SMichael Krufky
mxl111sf_calc_phy_tune_regs(u32 freq,u8 bw)784c66c920SMichael Krufky static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
794c66c920SMichael Krufky u8 bw)
804c66c920SMichael Krufky {
814c66c920SMichael Krufky u8 filt_bw;
824c66c920SMichael Krufky
834c66c920SMichael Krufky /* set channel bandwidth */
844c66c920SMichael Krufky switch (bw) {
854c66c920SMichael Krufky case 0: /* ATSC */
864c66c920SMichael Krufky filt_bw = 25;
874c66c920SMichael Krufky break;
884c66c920SMichael Krufky case 1: /* QAM */
894c66c920SMichael Krufky filt_bw = 69;
904c66c920SMichael Krufky break;
914c66c920SMichael Krufky case 6:
924c66c920SMichael Krufky filt_bw = 21;
934c66c920SMichael Krufky break;
944c66c920SMichael Krufky case 7:
954c66c920SMichael Krufky filt_bw = 42;
964c66c920SMichael Krufky break;
974c66c920SMichael Krufky case 8:
984c66c920SMichael Krufky filt_bw = 63;
994c66c920SMichael Krufky break;
1004c66c920SMichael Krufky default:
101c778edb5SHans Verkuil pr_err("%s: invalid bandwidth setting!", __func__);
1024c66c920SMichael Krufky return NULL;
1034c66c920SMichael Krufky }
1044c66c920SMichael Krufky
1054c66c920SMichael Krufky /* calculate RF channel */
1064c66c920SMichael Krufky freq /= 1000000;
1074c66c920SMichael Krufky
1084c66c920SMichael Krufky freq *= 64;
1094c66c920SMichael Krufky #if 0
1104c66c920SMichael Krufky /* do round */
1114c66c920SMichael Krufky freq += 0.5;
1124c66c920SMichael Krufky #endif
1134c66c920SMichael Krufky /* set bandwidth */
1144c66c920SMichael Krufky mxl_phy_tune_rf[0].data = filt_bw;
1154c66c920SMichael Krufky
1164c66c920SMichael Krufky /* set RF */
1174c66c920SMichael Krufky mxl_phy_tune_rf[1].data = (freq & 0xff);
1184c66c920SMichael Krufky mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
1194c66c920SMichael Krufky
1204c66c920SMichael Krufky /* start tune */
1214c66c920SMichael Krufky return mxl_phy_tune_rf;
1224c66c920SMichael Krufky }
1234c66c920SMichael Krufky
mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state * state)1244c66c920SMichael Krufky static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
1254c66c920SMichael Krufky {
1264c66c920SMichael Krufky int ret;
1274c66c920SMichael Krufky u8 ctrl;
1284c66c920SMichael Krufky #if 0
1294c66c920SMichael Krufky u16 iffcw;
1304c66c920SMichael Krufky u32 if_freq;
1314c66c920SMichael Krufky #endif
1324c66c920SMichael Krufky mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
1334c66c920SMichael Krufky state->cfg->invert_spectrum, state->cfg->if_freq);
1344c66c920SMichael Krufky
1354c66c920SMichael Krufky /* set IF polarity */
1364c66c920SMichael Krufky ctrl = state->cfg->invert_spectrum;
1374c66c920SMichael Krufky
1384c66c920SMichael Krufky ctrl |= state->cfg->if_freq;
1394c66c920SMichael Krufky
1404c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
1414c66c920SMichael Krufky if (mxl_fail(ret))
1424c66c920SMichael Krufky goto fail;
1434c66c920SMichael Krufky
1444c66c920SMichael Krufky #if 0
1454c66c920SMichael Krufky if_freq /= 1000000;
1464c66c920SMichael Krufky
1474c66c920SMichael Krufky /* do round */
1484c66c920SMichael Krufky if_freq += 0.5;
1494c66c920SMichael Krufky
1504c66c920SMichael Krufky if (MXL_IF_LO == state->cfg->if_freq) {
1514c66c920SMichael Krufky ctrl = 0x08;
1524c66c920SMichael Krufky iffcw = (u16)(if_freq / (108 * 4096));
1534c66c920SMichael Krufky } else if (MXL_IF_HI == state->cfg->if_freq) {
1544c66c920SMichael Krufky ctrl = 0x08;
1554c66c920SMichael Krufky iffcw = (u16)(if_freq / (216 * 4096));
1564c66c920SMichael Krufky } else {
1574c66c920SMichael Krufky ctrl = 0;
1584c66c920SMichael Krufky iffcw = 0;
1594c66c920SMichael Krufky }
1604c66c920SMichael Krufky
1614c66c920SMichael Krufky ctrl |= (iffcw >> 8);
1624c66c920SMichael Krufky #endif
1634c66c920SMichael Krufky ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
1644c66c920SMichael Krufky if (mxl_fail(ret))
1654c66c920SMichael Krufky goto fail;
1664c66c920SMichael Krufky
1674c66c920SMichael Krufky ctrl &= 0xf0;
1684c66c920SMichael Krufky ctrl |= 0x90;
1694c66c920SMichael Krufky
1704c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
1714c66c920SMichael Krufky if (mxl_fail(ret))
1724c66c920SMichael Krufky goto fail;
1734c66c920SMichael Krufky
1744c66c920SMichael Krufky #if 0
1754c66c920SMichael Krufky ctrl = iffcw & 0x00ff;
1764c66c920SMichael Krufky #endif
1774c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
178f7901f9bSMichael Krufky if (mxl_fail(ret))
179f7901f9bSMichael Krufky goto fail;
180f7901f9bSMichael Krufky
181f7901f9bSMichael Krufky state->if_freq = state->cfg->if_freq;
1824c66c920SMichael Krufky fail:
1834c66c920SMichael Krufky return ret;
1844c66c920SMichael Krufky }
1854c66c920SMichael Krufky
mxl1x1sf_tune_rf(struct dvb_frontend * fe,u32 freq,u8 bw)1864c66c920SMichael Krufky static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
1874c66c920SMichael Krufky {
1884c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
1894c66c920SMichael Krufky static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
1904c66c920SMichael Krufky int ret;
1914c66c920SMichael Krufky u8 mxl_mode;
1924c66c920SMichael Krufky
1934c66c920SMichael Krufky mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
1944c66c920SMichael Krufky
1954c66c920SMichael Krufky /* stop tune */
1964c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
1974c66c920SMichael Krufky if (mxl_fail(ret))
1984c66c920SMichael Krufky goto fail;
1994c66c920SMichael Krufky
2004c66c920SMichael Krufky /* check device mode */
2014c66c920SMichael Krufky ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
2024c66c920SMichael Krufky if (mxl_fail(ret))
2034c66c920SMichael Krufky goto fail;
2044c66c920SMichael Krufky
2054c66c920SMichael Krufky /* Fill out registers for channel tune */
2064c66c920SMichael Krufky reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
2074c66c920SMichael Krufky if (!reg_ctrl_array)
2084c66c920SMichael Krufky return -EINVAL;
2094c66c920SMichael Krufky
2104c66c920SMichael Krufky ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
2114c66c920SMichael Krufky if (mxl_fail(ret))
2124c66c920SMichael Krufky goto fail;
2134c66c920SMichael Krufky
2144c66c920SMichael Krufky if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
2154c66c920SMichael Krufky /* IF tuner mode only */
2164c66c920SMichael Krufky mxl1x1sf_tuner_top_master_ctrl(state, 0);
2174c66c920SMichael Krufky mxl1x1sf_tuner_top_master_ctrl(state, 1);
2184c66c920SMichael Krufky mxl1x1sf_tuner_set_if_output_freq(state);
2194c66c920SMichael Krufky }
2204c66c920SMichael Krufky
2214c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
2224c66c920SMichael Krufky if (mxl_fail(ret))
2234c66c920SMichael Krufky goto fail;
2244c66c920SMichael Krufky
2254c66c920SMichael Krufky if (state->cfg->ant_hunt)
2264c66c920SMichael Krufky state->cfg->ant_hunt(fe);
2274c66c920SMichael Krufky fail:
2284c66c920SMichael Krufky return ret;
2294c66c920SMichael Krufky }
2304c66c920SMichael Krufky
mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state * state,int * rf_synth_lock,int * ref_synth_lock)2314c66c920SMichael Krufky static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
2324c66c920SMichael Krufky int *rf_synth_lock,
2334c66c920SMichael Krufky int *ref_synth_lock)
2344c66c920SMichael Krufky {
2354c66c920SMichael Krufky int ret;
2364c66c920SMichael Krufky u8 data;
2374c66c920SMichael Krufky
2384c66c920SMichael Krufky *rf_synth_lock = 0;
2394c66c920SMichael Krufky *ref_synth_lock = 0;
2404c66c920SMichael Krufky
2414c66c920SMichael Krufky ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
2424c66c920SMichael Krufky if (mxl_fail(ret))
2434c66c920SMichael Krufky goto fail;
2444c66c920SMichael Krufky
2454c66c920SMichael Krufky *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
2464c66c920SMichael Krufky *rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0;
2474c66c920SMichael Krufky fail:
2484c66c920SMichael Krufky return ret;
2494c66c920SMichael Krufky }
2504c66c920SMichael Krufky
2514c66c920SMichael Krufky #if 0
2524c66c920SMichael Krufky static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
2534c66c920SMichael Krufky int onoff)
2544c66c920SMichael Krufky {
2554c66c920SMichael Krufky return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
2564c66c920SMichael Krufky onoff ? 1 : 0);
2574c66c920SMichael Krufky }
2584c66c920SMichael Krufky #endif
2594c66c920SMichael Krufky
2604c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
2614c66c920SMichael Krufky
mxl111sf_tuner_set_params(struct dvb_frontend * fe)26214d24d14SMauro Carvalho Chehab static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
2634c66c920SMichael Krufky {
26493ce675cSMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache;
26593ce675cSMauro Carvalho Chehab u32 delsys = c->delivery_system;
2664c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
2674c66c920SMichael Krufky int ret;
2684c66c920SMichael Krufky u8 bw;
2694c66c920SMichael Krufky
2704c66c920SMichael Krufky mxl_dbg("()");
2714c66c920SMichael Krufky
27293ce675cSMauro Carvalho Chehab switch (delsys) {
27393ce675cSMauro Carvalho Chehab case SYS_ATSC:
2744ef70775SMichael Krufky case SYS_ATSCMH:
2754c66c920SMichael Krufky bw = 0; /* ATSC */
2764c66c920SMichael Krufky break;
27793ce675cSMauro Carvalho Chehab case SYS_DVBC_ANNEX_B:
2784c66c920SMichael Krufky bw = 1; /* US CABLE */
2794c66c920SMichael Krufky break;
28093ce675cSMauro Carvalho Chehab case SYS_DVBT:
28193ce675cSMauro Carvalho Chehab switch (c->bandwidth_hz) {
28293ce675cSMauro Carvalho Chehab case 6000000:
2834c66c920SMichael Krufky bw = 6;
2844c66c920SMichael Krufky break;
28593ce675cSMauro Carvalho Chehab case 7000000:
2864c66c920SMichael Krufky bw = 7;
2874c66c920SMichael Krufky break;
28893ce675cSMauro Carvalho Chehab case 8000000:
2894c66c920SMichael Krufky bw = 8;
2904c66c920SMichael Krufky break;
2914c66c920SMichael Krufky default:
292c778edb5SHans Verkuil pr_err("%s: bandwidth not set!", __func__);
2934c66c920SMichael Krufky return -EINVAL;
2944c66c920SMichael Krufky }
29593ce675cSMauro Carvalho Chehab break;
29693ce675cSMauro Carvalho Chehab default:
297c778edb5SHans Verkuil pr_err("%s: modulation type not supported!", __func__);
2984c66c920SMichael Krufky return -EINVAL;
2994c66c920SMichael Krufky }
30093ce675cSMauro Carvalho Chehab ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
3014c66c920SMichael Krufky if (mxl_fail(ret))
3024c66c920SMichael Krufky goto fail;
3034c66c920SMichael Krufky
30493ce675cSMauro Carvalho Chehab state->frequency = c->frequency;
305c6f56e7dSMauro Carvalho Chehab state->bandwidth = c->bandwidth_hz;
3064c66c920SMichael Krufky fail:
3074c66c920SMichael Krufky return ret;
3084c66c920SMichael Krufky }
3094c66c920SMichael Krufky
3104c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
3114c66c920SMichael Krufky
3124c66c920SMichael Krufky #if 0
3134c66c920SMichael Krufky static int mxl111sf_tuner_init(struct dvb_frontend *fe)
3144c66c920SMichael Krufky {
3154c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
3164c66c920SMichael Krufky int ret;
3174c66c920SMichael Krufky
3184c66c920SMichael Krufky /* wake from standby handled by usb driver */
3194c66c920SMichael Krufky
3204c66c920SMichael Krufky return ret;
3214c66c920SMichael Krufky }
3224c66c920SMichael Krufky
3234c66c920SMichael Krufky static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
3244c66c920SMichael Krufky {
3254c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
3264c66c920SMichael Krufky int ret;
3274c66c920SMichael Krufky
3284c66c920SMichael Krufky /* enter standby mode handled by usb driver */
3294c66c920SMichael Krufky
3304c66c920SMichael Krufky return ret;
3314c66c920SMichael Krufky }
3324c66c920SMichael Krufky #endif
3334c66c920SMichael Krufky
3344c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
3354c66c920SMichael Krufky
mxl111sf_tuner_get_status(struct dvb_frontend * fe,u32 * status)3364c66c920SMichael Krufky static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
3374c66c920SMichael Krufky {
3384c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
3394c66c920SMichael Krufky int rf_locked, ref_locked, ret;
3404c66c920SMichael Krufky
3414c66c920SMichael Krufky *status = 0;
3424c66c920SMichael Krufky
3434c66c920SMichael Krufky ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
3444c66c920SMichael Krufky if (mxl_fail(ret))
3454c66c920SMichael Krufky goto fail;
3464c66c920SMichael Krufky mxl_info("%s%s", rf_locked ? "rf locked " : "",
3474c66c920SMichael Krufky ref_locked ? "ref locked" : "");
3484c66c920SMichael Krufky
3494c66c920SMichael Krufky if ((rf_locked) || (ref_locked))
3504c66c920SMichael Krufky *status |= TUNER_STATUS_LOCKED;
3514c66c920SMichael Krufky fail:
3524c66c920SMichael Krufky return ret;
3534c66c920SMichael Krufky }
3544c66c920SMichael Krufky
mxl111sf_get_rf_strength(struct dvb_frontend * fe,u16 * strength)3554c66c920SMichael Krufky static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
3564c66c920SMichael Krufky {
3574c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
3584c66c920SMichael Krufky u8 val1, val2;
3594c66c920SMichael Krufky int ret;
3604c66c920SMichael Krufky
3614c66c920SMichael Krufky *strength = 0;
3624c66c920SMichael Krufky
3634c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
3644c66c920SMichael Krufky if (mxl_fail(ret))
3654c66c920SMichael Krufky goto fail;
3664c66c920SMichael Krufky ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
3674c66c920SMichael Krufky if (mxl_fail(ret))
3684c66c920SMichael Krufky goto fail;
3694c66c920SMichael Krufky ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
3704c66c920SMichael Krufky if (mxl_fail(ret))
3714c66c920SMichael Krufky goto fail;
3724c66c920SMichael Krufky
3734c66c920SMichael Krufky *strength = val1 | ((val2 & 0x07) << 8);
3744c66c920SMichael Krufky fail:
3754c66c920SMichael Krufky ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
3764c66c920SMichael Krufky mxl_fail(ret);
3774c66c920SMichael Krufky
3784c66c920SMichael Krufky return ret;
3794c66c920SMichael Krufky }
3804c66c920SMichael Krufky
3814c66c920SMichael Krufky /* ------------------------------------------------------------------------ */
3824c66c920SMichael Krufky
mxl111sf_tuner_get_frequency(struct dvb_frontend * fe,u32 * frequency)3834c66c920SMichael Krufky static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
3844c66c920SMichael Krufky {
3854c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
3864c66c920SMichael Krufky *frequency = state->frequency;
3874c66c920SMichael Krufky return 0;
3884c66c920SMichael Krufky }
3894c66c920SMichael Krufky
mxl111sf_tuner_get_bandwidth(struct dvb_frontend * fe,u32 * bandwidth)3904c66c920SMichael Krufky static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
3914c66c920SMichael Krufky {
3924c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
3934c66c920SMichael Krufky *bandwidth = state->bandwidth;
3944c66c920SMichael Krufky return 0;
3954c66c920SMichael Krufky }
3964c66c920SMichael Krufky
mxl111sf_tuner_get_if_frequency(struct dvb_frontend * fe,u32 * frequency)397f7901f9bSMichael Krufky static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
398f7901f9bSMichael Krufky u32 *frequency)
399f7901f9bSMichael Krufky {
400f7901f9bSMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
401f7901f9bSMichael Krufky
402f7901f9bSMichael Krufky *frequency = 0;
403f7901f9bSMichael Krufky
404f7901f9bSMichael Krufky switch (state->if_freq) {
405f7901f9bSMichael Krufky case MXL_IF_4_0: /* 4.0 MHz */
406f7901f9bSMichael Krufky *frequency = 4000000;
407f7901f9bSMichael Krufky break;
408f7901f9bSMichael Krufky case MXL_IF_4_5: /* 4.5 MHz */
409f7901f9bSMichael Krufky *frequency = 4500000;
410f7901f9bSMichael Krufky break;
411f7901f9bSMichael Krufky case MXL_IF_4_57: /* 4.57 MHz */
412f7901f9bSMichael Krufky *frequency = 4570000;
413f7901f9bSMichael Krufky break;
414f7901f9bSMichael Krufky case MXL_IF_5_0: /* 5.0 MHz */
415f7901f9bSMichael Krufky *frequency = 5000000;
416f7901f9bSMichael Krufky break;
417f7901f9bSMichael Krufky case MXL_IF_5_38: /* 5.38 MHz */
418f7901f9bSMichael Krufky *frequency = 5380000;
419f7901f9bSMichael Krufky break;
420f7901f9bSMichael Krufky case MXL_IF_6_0: /* 6.0 MHz */
421f7901f9bSMichael Krufky *frequency = 6000000;
422f7901f9bSMichael Krufky break;
423f7901f9bSMichael Krufky case MXL_IF_6_28: /* 6.28 MHz */
424f7901f9bSMichael Krufky *frequency = 6280000;
425f7901f9bSMichael Krufky break;
426f7901f9bSMichael Krufky case MXL_IF_7_2: /* 7.2 MHz */
427f7901f9bSMichael Krufky *frequency = 7200000;
428f7901f9bSMichael Krufky break;
429f7901f9bSMichael Krufky case MXL_IF_35_25: /* 35.25 MHz */
430f7901f9bSMichael Krufky *frequency = 35250000;
431f7901f9bSMichael Krufky break;
432f7901f9bSMichael Krufky case MXL_IF_36: /* 36 MHz */
433f7901f9bSMichael Krufky *frequency = 36000000;
434f7901f9bSMichael Krufky break;
435f7901f9bSMichael Krufky case MXL_IF_36_15: /* 36.15 MHz */
436f7901f9bSMichael Krufky *frequency = 36150000;
437f7901f9bSMichael Krufky break;
438f7901f9bSMichael Krufky case MXL_IF_44: /* 44 MHz */
439f7901f9bSMichael Krufky *frequency = 44000000;
440f7901f9bSMichael Krufky break;
441f7901f9bSMichael Krufky }
442f7901f9bSMichael Krufky return 0;
443f7901f9bSMichael Krufky }
444f7901f9bSMichael Krufky
mxl111sf_tuner_release(struct dvb_frontend * fe)445194ced7aSMax Kellermann static void mxl111sf_tuner_release(struct dvb_frontend *fe)
4464c66c920SMichael Krufky {
4474c66c920SMichael Krufky struct mxl111sf_tuner_state *state = fe->tuner_priv;
4484c66c920SMichael Krufky mxl_dbg("()");
4494c66c920SMichael Krufky kfree(state);
4504c66c920SMichael Krufky fe->tuner_priv = NULL;
4514c66c920SMichael Krufky }
4524c66c920SMichael Krufky
4534c66c920SMichael Krufky /* ------------------------------------------------------------------------- */
4544c66c920SMichael Krufky
45556e247a5SJulia Lawall static const struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
4564c66c920SMichael Krufky .info = {
4574c66c920SMichael Krufky .name = "MaxLinear MxL111SF",
4584c66c920SMichael Krufky #if 0
459a3f90c75SMauro Carvalho Chehab .frequency_min_hz = ,
460a3f90c75SMauro Carvalho Chehab .frequency_max_hz = ,
461a3f90c75SMauro Carvalho Chehab .frequency_step_hz = ,
4624c66c920SMichael Krufky #endif
4634c66c920SMichael Krufky },
4644c66c920SMichael Krufky #if 0
4654c66c920SMichael Krufky .init = mxl111sf_tuner_init,
4664c66c920SMichael Krufky .sleep = mxl111sf_tuner_sleep,
4674c66c920SMichael Krufky #endif
4684c66c920SMichael Krufky .set_params = mxl111sf_tuner_set_params,
4694c66c920SMichael Krufky .get_status = mxl111sf_tuner_get_status,
4704c66c920SMichael Krufky .get_rf_strength = mxl111sf_get_rf_strength,
4714c66c920SMichael Krufky .get_frequency = mxl111sf_tuner_get_frequency,
4724c66c920SMichael Krufky .get_bandwidth = mxl111sf_tuner_get_bandwidth,
473f7901f9bSMichael Krufky .get_if_frequency = mxl111sf_tuner_get_if_frequency,
4744c66c920SMichael Krufky .release = mxl111sf_tuner_release,
4754c66c920SMichael Krufky };
4764c66c920SMichael Krufky
mxl111sf_tuner_attach(struct dvb_frontend * fe,struct mxl111sf_state * mxl_state,const struct mxl111sf_tuner_config * cfg)4774c66c920SMichael Krufky struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
4784c66c920SMichael Krufky struct mxl111sf_state *mxl_state,
47940205163SJulia Lawall const struct mxl111sf_tuner_config *cfg)
4804c66c920SMichael Krufky {
4814c66c920SMichael Krufky struct mxl111sf_tuner_state *state = NULL;
4824c66c920SMichael Krufky
4834c66c920SMichael Krufky mxl_dbg("()");
4844c66c920SMichael Krufky
4854c66c920SMichael Krufky state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
4864c66c920SMichael Krufky if (state == NULL)
4874c66c920SMichael Krufky return NULL;
4884c66c920SMichael Krufky
4894c66c920SMichael Krufky state->mxl_state = mxl_state;
4904c66c920SMichael Krufky state->cfg = cfg;
4914c66c920SMichael Krufky
4924c66c920SMichael Krufky memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
4934c66c920SMichael Krufky sizeof(struct dvb_tuner_ops));
4944c66c920SMichael Krufky
4954c66c920SMichael Krufky fe->tuner_priv = state;
4964c66c920SMichael Krufky return fe;
4974c66c920SMichael Krufky }
4984c66c920SMichael Krufky EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
4994c66c920SMichael Krufky
5004c66c920SMichael Krufky MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
50108e10972SMichael Krufky MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
5024c66c920SMichael Krufky MODULE_LICENSE("GPL");
5034c66c920SMichael Krufky MODULE_VERSION("0.1");
504