linux/drivers/media/dvb/frontends/au8522_decoder.c
<<
>>
Prefs
   1/*
   2 * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder
   3 *
   4 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
   5 * Copyright (C) 2005-2008 Auvitek International, Ltd.
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * As published by the Free Software Foundation; either version 2
  10 * of the License, or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20 * 02110-1301, USA.
  21 */
  22
  23/* Developer notes:
  24 *
  25 * VBI support is not yet working
  26 * Enough is implemented here for CVBS and S-Video inputs, but the actual
  27 *  analog demodulator code isn't implemented (not needed for xc5000 since it
  28 *  has its own demodulator and outputs CVBS)
  29 *
  30 */
  31
  32#include <linux/kernel.h>
  33#include <linux/slab.h>
  34#include <linux/videodev2.h>
  35#include <linux/i2c.h>
  36#include <linux/delay.h>
  37#include <media/v4l2-common.h>
  38#include <media/v4l2-chip-ident.h>
  39#include <media/v4l2-device.h>
  40#include "au8522.h"
  41#include "au8522_priv.h"
  42
  43MODULE_AUTHOR("Devin Heitmueller");
  44MODULE_LICENSE("GPL");
  45
  46static int au8522_analog_debug;
  47
  48
  49module_param_named(analog_debug, au8522_analog_debug, int, 0644);
  50
  51MODULE_PARM_DESC(analog_debug,
  52                 "Analog debugging messages [0=Off (default) 1=On]");
  53
  54struct au8522_register_config {
  55        u16 reg_name;
  56        u8 reg_val[8];
  57};
  58
  59
  60/* Video Decoder Filter Coefficients
  61   The values are as follows from left to right
  62   0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
  63*/
  64static const struct au8522_register_config filter_coef[] = {
  65        {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
  66        {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
  67        {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
  68        {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} },
  69        {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} },
  70        {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} },
  71        {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} },
  72        {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} },
  73        {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} },
  74        {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} },
  75        {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} },
  76        {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} },
  77        {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} },
  78        {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} },
  79        {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} },
  80        {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} },
  81        {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} },
  82        {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} },
  83        {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} },
  84        {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} },
  85        {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} },
  86        {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} },
  87        {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} },
  88        {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} },
  89        {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} },
  90        {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} },
  91        {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} },
  92        {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} },
  93        {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} },
  94        {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} },
  95
  96};
  97#define NUM_FILTER_COEF (sizeof(filter_coef)\
  98                         / sizeof(struct au8522_register_config))
  99
 100
 101/* Registers 0x060b through 0x0652 are the LP Filter coefficients
 102   The values are as follows from left to right
 103   0="SIF" 1="ATVRF/ATVRF13"
 104   Note: the "ATVRF/ATVRF13" mode has never been tested
 105*/
 106static const struct au8522_register_config lpfilter_coef[] = {
 107        {0x060b, {0x21, 0x0b} },
 108        {0x060c, {0xad, 0xad} },
 109        {0x060d, {0x70, 0xf0} },
 110        {0x060e, {0xea, 0xe9} },
 111        {0x060f, {0xdd, 0xdd} },
 112        {0x0610, {0x08, 0x64} },
 113        {0x0611, {0x60, 0x60} },
 114        {0x0612, {0xf8, 0xb2} },
 115        {0x0613, {0x01, 0x02} },
 116        {0x0614, {0xe4, 0xb4} },
 117        {0x0615, {0x19, 0x02} },
 118        {0x0616, {0xae, 0x2e} },
 119        {0x0617, {0xee, 0xc5} },
 120        {0x0618, {0x56, 0x56} },
 121        {0x0619, {0x30, 0x58} },
 122        {0x061a, {0xf9, 0xf8} },
 123        {0x061b, {0x24, 0x64} },
 124        {0x061c, {0x07, 0x07} },
 125        {0x061d, {0x30, 0x30} },
 126        {0x061e, {0xa9, 0xed} },
 127        {0x061f, {0x09, 0x0b} },
 128        {0x0620, {0x42, 0xc2} },
 129        {0x0621, {0x1d, 0x2a} },
 130        {0x0622, {0xd6, 0x56} },
 131        {0x0623, {0x95, 0x8b} },
 132        {0x0624, {0x2b, 0x2b} },
 133        {0x0625, {0x30, 0x24} },
 134        {0x0626, {0x3e, 0x3e} },
 135        {0x0627, {0x62, 0xe2} },
 136        {0x0628, {0xe9, 0xf5} },
 137        {0x0629, {0x99, 0x19} },
 138        {0x062a, {0xd4, 0x11} },
 139        {0x062b, {0x03, 0x04} },
 140        {0x062c, {0xb5, 0x85} },
 141        {0x062d, {0x1e, 0x20} },
 142        {0x062e, {0x2a, 0xea} },
 143        {0x062f, {0xd7, 0xd2} },
 144        {0x0630, {0x15, 0x15} },
 145        {0x0631, {0xa3, 0xa9} },
 146        {0x0632, {0x1f, 0x1f} },
 147        {0x0633, {0xf9, 0xd1} },
 148        {0x0634, {0xc0, 0xc3} },
 149        {0x0635, {0x4d, 0x8d} },
 150        {0x0636, {0x21, 0x31} },
 151        {0x0637, {0x83, 0x83} },
 152        {0x0638, {0x08, 0x8c} },
 153        {0x0639, {0x19, 0x19} },
 154        {0x063a, {0x45, 0xa5} },
 155        {0x063b, {0xef, 0xec} },
 156        {0x063c, {0x8a, 0x8a} },
 157        {0x063d, {0xf4, 0xf6} },
 158        {0x063e, {0x8f, 0x8f} },
 159        {0x063f, {0x44, 0x0c} },
 160        {0x0640, {0xef, 0xf0} },
 161        {0x0641, {0x66, 0x66} },
 162        {0x0642, {0xcc, 0xd2} },
 163        {0x0643, {0x41, 0x41} },
 164        {0x0644, {0x63, 0x93} },
 165        {0x0645, {0x8e, 0x8e} },
 166        {0x0646, {0xa2, 0x42} },
 167        {0x0647, {0x7b, 0x7b} },
 168        {0x0648, {0x04, 0x04} },
 169        {0x0649, {0x00, 0x00} },
 170        {0x064a, {0x40, 0x40} },
 171        {0x064b, {0x8c, 0x98} },
 172        {0x064c, {0x00, 0x00} },
 173        {0x064d, {0x63, 0xc3} },
 174        {0x064e, {0x04, 0x04} },
 175        {0x064f, {0x20, 0x20} },
 176        {0x0650, {0x00, 0x00} },
 177        {0x0651, {0x40, 0x40} },
 178        {0x0652, {0x01, 0x01} },
 179};
 180#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
 181                           / sizeof(struct au8522_register_config))
 182
 183static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
 184{
 185        return container_of(sd, struct au8522_state, sd);
 186}
 187
 188static void setup_vbi(struct au8522_state *state, int aud_input)
 189{
 190        int i;
 191
 192        /* These are set to zero regardless of what mode we're in */
 193        au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
 194        au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
 195        au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
 196        au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
 197        au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
 198        au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
 199        au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
 200        au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
 201        au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
 202        au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,
 203                        0x00);
 204        au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,
 205                        0x00);
 206        au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,
 207                        0x00);
 208
 209        /* Setup the VBI registers */
 210        for (i = 0x30; i < 0x60; i++)
 211                au8522_writereg(state, i, 0x40);
 212
 213        /* For some reason, every register is 0x40 except register 0x44
 214           (confirmed via the HVR-950q USB capture) */
 215        au8522_writereg(state, 0x44, 0x60);
 216
 217        /* Enable VBI (we always do this regardless of whether the user is
 218           viewing closed caption info) */
 219        au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H,
 220                        AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON);
 221
 222}
 223
 224static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
 225{
 226        int i;
 227        int filter_coef_type;
 228
 229        /* Provide reasonable defaults for picture tuning values */
 230        au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
 231        au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
 232        state->brightness = 0xed - 128;
 233        au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
 234        state->contrast = 0x79;
 235        au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
 236        au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
 237        state->saturation = 0x80;
 238        au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
 239        au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
 240        state->hue = 0x00;
 241
 242        /* Other decoder registers */
 243        au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
 244
 245        if (input_mode == 0x23) {
 246                /* S-Video input mapping */
 247                au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
 248        } else {
 249                /* All other modes (CVBS/ATVRF etc.) */
 250                au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
 251        }
 252
 253        au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
 254                        AU8522_TVDEC_PGA_REG012H_CVBS);
 255        au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
 256                        AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
 257        au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
 258                        AU8522_TVDED_DBG_MODE_REG060H_CVBS);
 259        au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
 260                        AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
 261        au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
 262                        AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
 263        au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
 264                        AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
 265        au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
 266                        AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
 267        au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
 268                        AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
 269        au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
 270                        AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
 271        au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
 272                        AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
 273        au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
 274                        AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
 275        au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
 276                        AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
 277        au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
 278                        AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
 279        au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
 280                        AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
 281        if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
 282            input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
 283                au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
 284                                AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
 285                au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
 286                                AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO);
 287        } else {
 288                au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
 289                                AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
 290                au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
 291                                AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
 292        }
 293        au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
 294                        AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
 295        au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
 296                        AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
 297        au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
 298                        AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
 299        au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
 300        au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
 301        au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
 302                        AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
 303        au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
 304        au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
 305        au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
 306                        AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
 307        au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
 308                        AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
 309        au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
 310                        AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
 311        au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
 312                        AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
 313        au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
 314                        AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
 315        au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
 316                        AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
 317        au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
 318                        AU8522_TOREGAAGC_REG0E5H_CVBS);
 319        au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
 320
 321        setup_vbi(state, 0);
 322
 323        if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
 324            input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
 325                /* Despite what the table says, for the HVR-950q we still need
 326                   to be in CVBS mode for the S-Video input (reason unknown). */
 327                /* filter_coef_type = 3; */
 328                filter_coef_type = 5;
 329        } else {
 330                filter_coef_type = 5;
 331        }
 332
 333        /* Load the Video Decoder Filter Coefficients */
 334        for (i = 0; i < NUM_FILTER_COEF; i++) {
 335                au8522_writereg(state, filter_coef[i].reg_name,
 336                                filter_coef[i].reg_val[filter_coef_type]);
 337        }
 338
 339        /* It's not clear what these registers are for, but they are always
 340           set to the same value regardless of what mode we're in */
 341        au8522_writereg(state, AU8522_REG42EH, 0x87);
 342        au8522_writereg(state, AU8522_REG42FH, 0xa2);
 343        au8522_writereg(state, AU8522_REG430H, 0xbf);
 344        au8522_writereg(state, AU8522_REG431H, 0xcb);
 345        au8522_writereg(state, AU8522_REG432H, 0xa1);
 346        au8522_writereg(state, AU8522_REG433H, 0x41);
 347        au8522_writereg(state, AU8522_REG434H, 0x88);
 348        au8522_writereg(state, AU8522_REG435H, 0xc2);
 349        au8522_writereg(state, AU8522_REG436H, 0x3c);
 350}
 351
 352static void au8522_setup_cvbs_mode(struct au8522_state *state)
 353{
 354        /* here we're going to try the pre-programmed route */
 355        au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
 356                        AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
 357
 358        /* PGA in automatic mode */
 359        au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
 360
 361        /* Enable clamping control */
 362        au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
 363
 364        au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
 365                        AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
 366
 367        setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
 368
 369        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 370                        AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 371}
 372
 373static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
 374{
 375        /* here we're going to try the pre-programmed route */
 376        au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
 377                        AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
 378
 379        /* It's not clear why we have to have the PGA in automatic mode while
 380           enabling clamp control, but it's what Windows does */
 381        au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
 382
 383        /* Enable clamping control */
 384        au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
 385
 386        /* Disable automatic PGA (since the CVBS is coming from the tuner) */
 387        au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
 388
 389        /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
 390        au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
 391                        AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
 392
 393        setup_decoder_defaults(state,
 394                               AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
 395
 396        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 397                        AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 398}
 399
 400static void au8522_setup_svideo_mode(struct au8522_state *state)
 401{
 402        au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
 403                        AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
 404
 405        /* Set input to Y on Channe1, C on Channel 3 */
 406        au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
 407                        AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
 408
 409        /* PGA in automatic mode */
 410        au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
 411
 412        /* Enable clamping control */
 413        au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
 414
 415        setup_decoder_defaults(state,
 416                               AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
 417
 418        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 419                        AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 420}
 421
 422/* ----------------------------------------------------------------------- */
 423
 424static void disable_audio_input(struct au8522_state *state)
 425{
 426        au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
 427        au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
 428        au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
 429
 430        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
 431        au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
 432
 433        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 434                        AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
 435}
 436
 437/* 0=disable, 1=SIF */
 438static void set_audio_input(struct au8522_state *state, int aud_input)
 439{
 440        int i;
 441
 442        /* Note that this function needs to be used in conjunction with setting
 443           the input routing via register 0x81 */
 444
 445        if (aud_input == AU8522_AUDIO_NONE) {
 446                disable_audio_input(state);
 447                return;
 448        }
 449
 450        if (aud_input != AU8522_AUDIO_SIF) {
 451                /* The caller asked for a mode we don't currently support */
 452                printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
 453                       aud_input);
 454                return;
 455        }
 456
 457        /* Load the Audio Decoder Filter Coefficients */
 458        for (i = 0; i < NUM_LPFILTER_COEF; i++) {
 459                au8522_writereg(state, lpfilter_coef[i].reg_name,
 460                                lpfilter_coef[i].reg_val[0]);
 461        }
 462
 463        /* Setup audio */
 464        au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
 465        au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
 466        au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
 467        au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
 468        au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
 469        msleep(150);
 470        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
 471        msleep(1);
 472        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
 473        msleep(50);
 474        au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
 475        au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
 476        au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
 477        msleep(80);
 478        au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
 479        au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
 480        au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
 481        au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
 482        msleep(70);
 483        au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
 484        au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
 485        au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
 486}
 487
 488/* ----------------------------------------------------------------------- */
 489
 490static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 491{
 492        struct au8522_state *state = to_state(sd);
 493
 494        switch (ctrl->id) {
 495        case V4L2_CID_BRIGHTNESS:
 496                state->brightness = ctrl->value;
 497                au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
 498                                ctrl->value - 128);
 499                break;
 500        case V4L2_CID_CONTRAST:
 501                state->contrast = ctrl->value;
 502                au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
 503                                ctrl->value);
 504                break;
 505        case V4L2_CID_SATURATION:
 506                state->saturation = ctrl->value;
 507                au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
 508                                ctrl->value);
 509                au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
 510                                ctrl->value);
 511                break;
 512        case V4L2_CID_HUE:
 513                state->hue = ctrl->value;
 514                au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
 515                                ctrl->value >> 8);
 516                au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
 517                                ctrl->value & 0xFF);
 518                break;
 519        case V4L2_CID_AUDIO_VOLUME:
 520        case V4L2_CID_AUDIO_BASS:
 521        case V4L2_CID_AUDIO_TREBLE:
 522        case V4L2_CID_AUDIO_BALANCE:
 523        case V4L2_CID_AUDIO_MUTE:
 524                /* Not yet implemented */
 525        default:
 526                return -EINVAL;
 527        }
 528
 529        return 0;
 530}
 531
 532static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 533{
 534        struct au8522_state *state = to_state(sd);
 535
 536        /* Note that we are using values cached in the state structure instead
 537           of reading the registers due to issues with i2c reads not working
 538           properly/consistently yet on the HVR-950q */
 539
 540        switch (ctrl->id) {
 541        case V4L2_CID_BRIGHTNESS:
 542                ctrl->value = state->brightness;
 543                break;
 544        case V4L2_CID_CONTRAST:
 545                ctrl->value = state->contrast;
 546                break;
 547        case V4L2_CID_SATURATION:
 548                ctrl->value = state->saturation;
 549                break;
 550        case V4L2_CID_HUE:
 551                ctrl->value = state->hue;
 552                break;
 553        case V4L2_CID_AUDIO_VOLUME:
 554        case V4L2_CID_AUDIO_BASS:
 555        case V4L2_CID_AUDIO_TREBLE:
 556        case V4L2_CID_AUDIO_BALANCE:
 557        case V4L2_CID_AUDIO_MUTE:
 558                /* Not yet supported */
 559        default:
 560                return -EINVAL;
 561        }
 562
 563        return 0;
 564}
 565
 566/* ----------------------------------------------------------------------- */
 567
 568#ifdef CONFIG_VIDEO_ADV_DEBUG
 569static int au8522_g_register(struct v4l2_subdev *sd,
 570                             struct v4l2_dbg_register *reg)
 571{
 572        struct i2c_client *client = v4l2_get_subdevdata(sd);
 573        struct au8522_state *state = to_state(sd);
 574
 575        if (!v4l2_chip_match_i2c_client(client, &reg->match))
 576                return -EINVAL;
 577        if (!capable(CAP_SYS_ADMIN))
 578                return -EPERM;
 579        reg->val = au8522_readreg(state, reg->reg & 0xffff);
 580        return 0;
 581}
 582
 583static int au8522_s_register(struct v4l2_subdev *sd,
 584                             struct v4l2_dbg_register *reg)
 585{
 586        struct i2c_client *client = v4l2_get_subdevdata(sd);
 587        struct au8522_state *state = to_state(sd);
 588
 589        if (!v4l2_chip_match_i2c_client(client, &reg->match))
 590                return -EINVAL;
 591        if (!capable(CAP_SYS_ADMIN))
 592                return -EPERM;
 593        au8522_writereg(state, reg->reg, reg->val & 0xff);
 594        return 0;
 595}
 596#endif
 597
 598static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
 599{
 600        struct au8522_state *state = to_state(sd);
 601
 602        if (enable) {
 603                au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 604                                0x01);
 605                msleep(1);
 606                au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 607                                AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
 608        } else {
 609                /* This does not completely power down the device
 610                   (it only reduces it from around 140ma to 80ma) */
 611                au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
 612                                1 << 5);
 613        }
 614        return 0;
 615}
 616
 617static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 618{
 619        switch (qc->id) {
 620        case V4L2_CID_CONTRAST:
 621                return v4l2_ctrl_query_fill(qc, 0, 255, 1,
 622                                            AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
 623        case V4L2_CID_BRIGHTNESS:
 624                return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
 625        case V4L2_CID_SATURATION:
 626                return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
 627        case V4L2_CID_HUE:
 628                return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
 629        default:
 630                break;
 631        }
 632
 633        qc->type = 0;
 634        return -EINVAL;
 635}
 636
 637static int au8522_reset(struct v4l2_subdev *sd, u32 val)
 638{
 639        struct au8522_state *state = to_state(sd);
 640
 641        state->operational_mode = AU8522_ANALOG_MODE;
 642
 643        /* Clear out any state associated with the digital side of the
 644           chip, so that when it gets powered back up it won't think
 645           that it is already tuned */
 646        state->current_frequency = 0;
 647
 648        au8522_writereg(state, 0xa4, 1 << 5);
 649
 650        return 0;
 651}
 652
 653static int au8522_s_video_routing(struct v4l2_subdev *sd,
 654                                        u32 input, u32 output, u32 config)
 655{
 656        struct au8522_state *state = to_state(sd);
 657
 658        au8522_reset(sd, 0);
 659
 660        /* Jam open the i2c gate to the tuner.  We do this here to handle the
 661           case where the user went into digital mode (causing the gate to be
 662           closed), and then came back to analog mode */
 663        au8522_writereg(state, 0x106, 1);
 664
 665        if (input == AU8522_COMPOSITE_CH1) {
 666                au8522_setup_cvbs_mode(state);
 667        } else if (input == AU8522_SVIDEO_CH13) {
 668                au8522_setup_svideo_mode(state);
 669        } else if (input == AU8522_COMPOSITE_CH4_SIF) {
 670                au8522_setup_cvbs_tuner_mode(state);
 671        } else {
 672                printk(KERN_ERR "au8522 mode not currently supported\n");
 673                return -EINVAL;
 674        }
 675        return 0;
 676}
 677
 678static int au8522_s_audio_routing(struct v4l2_subdev *sd,
 679                                        u32 input, u32 output, u32 config)
 680{
 681        struct au8522_state *state = to_state(sd);
 682        set_audio_input(state, input);
 683        return 0;
 684}
 685
 686static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 687{
 688        int val = 0;
 689        struct au8522_state *state = to_state(sd);
 690        u8 lock_status;
 691
 692        /* Interrogate the decoder to see if we are getting a real signal */
 693        lock_status = au8522_readreg(state, 0x00);
 694        if (lock_status == 0xa2)
 695                vt->signal = 0xffff;
 696        else
 697                vt->signal = 0x00;
 698
 699        vt->capability |=
 700                V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
 701                V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
 702
 703        val = V4L2_TUNER_SUB_MONO;
 704        vt->rxsubchans = val;
 705        vt->audmode = V4L2_TUNER_MODE_STEREO;
 706        return 0;
 707}
 708
 709static int au8522_g_chip_ident(struct v4l2_subdev *sd,
 710                               struct v4l2_dbg_chip_ident *chip)
 711{
 712        struct au8522_state *state = to_state(sd);
 713        struct i2c_client *client = v4l2_get_subdevdata(sd);
 714
 715        return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
 716}
 717
 718static int au8522_log_status(struct v4l2_subdev *sd)
 719{
 720        /* FIXME: Add some status info here */
 721        return 0;
 722}
 723
 724/* ----------------------------------------------------------------------- */
 725
 726static const struct v4l2_subdev_core_ops au8522_core_ops = {
 727        .log_status = au8522_log_status,
 728        .g_chip_ident = au8522_g_chip_ident,
 729        .g_ctrl = au8522_g_ctrl,
 730        .s_ctrl = au8522_s_ctrl,
 731        .queryctrl = au8522_queryctrl,
 732        .reset = au8522_reset,
 733#ifdef CONFIG_VIDEO_ADV_DEBUG
 734        .g_register = au8522_g_register,
 735        .s_register = au8522_s_register,
 736#endif
 737};
 738
 739static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
 740        .g_tuner = au8522_g_tuner,
 741};
 742
 743static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
 744        .s_routing = au8522_s_audio_routing,
 745};
 746
 747static const struct v4l2_subdev_video_ops au8522_video_ops = {
 748        .s_routing = au8522_s_video_routing,
 749        .s_stream = au8522_s_stream,
 750};
 751
 752static const struct v4l2_subdev_ops au8522_ops = {
 753        .core = &au8522_core_ops,
 754        .tuner = &au8522_tuner_ops,
 755        .audio = &au8522_audio_ops,
 756        .video = &au8522_video_ops,
 757};
 758
 759/* ----------------------------------------------------------------------- */
 760
 761static int au8522_probe(struct i2c_client *client,
 762                        const struct i2c_device_id *did)
 763{
 764        struct au8522_state *state;
 765        struct v4l2_subdev *sd;
 766        int instance;
 767        struct au8522_config *demod_config;
 768
 769        /* Check if the adapter supports the needed features */
 770        if (!i2c_check_functionality(client->adapter,
 771                                     I2C_FUNC_SMBUS_BYTE_DATA)) {
 772                return -EIO;
 773        }
 774
 775        /* allocate memory for the internal state */
 776        instance = au8522_get_state(&state, client->adapter, client->addr);
 777        switch (instance) {
 778        case 0:
 779                printk(KERN_ERR "au8522_decoder allocation failed\n");
 780                return -EIO;
 781        case 1:
 782                /* new demod instance */
 783                printk(KERN_INFO "au8522_decoder creating new instance...\n");
 784                break;
 785        default:
 786                /* existing demod instance */
 787                printk(KERN_INFO "au8522_decoder attach existing instance.\n");
 788                break;
 789        }
 790
 791        demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
 792        if (demod_config == NULL) {
 793                if (instance == 1)
 794                        kfree(state);
 795                return -ENOMEM;
 796        }
 797        demod_config->demod_address = 0x8e >> 1;
 798
 799        state->config = demod_config;
 800        state->i2c = client->adapter;
 801
 802        sd = &state->sd;
 803        v4l2_i2c_subdev_init(sd, client, &au8522_ops);
 804
 805        state->c = client;
 806        state->vid_input = AU8522_COMPOSITE_CH1;
 807        state->aud_input = AU8522_AUDIO_NONE;
 808        state->id = 8522;
 809        state->rev = 0;
 810
 811        /* Jam open the i2c gate to the tuner */
 812        au8522_writereg(state, 0x106, 1);
 813
 814        return 0;
 815}
 816
 817static int au8522_remove(struct i2c_client *client)
 818{
 819        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 820        v4l2_device_unregister_subdev(sd);
 821        au8522_release_state(to_state(sd));
 822        return 0;
 823}
 824
 825static const struct i2c_device_id au8522_id[] = {
 826        {"au8522", 0},
 827        {}
 828};
 829
 830MODULE_DEVICE_TABLE(i2c, au8522_id);
 831
 832static struct i2c_driver au8522_driver = {
 833        .driver = {
 834                .owner  = THIS_MODULE,
 835                .name   = "au8522",
 836        },
 837        .probe          = au8522_probe,
 838        .remove         = au8522_remove,
 839        .id_table       = au8522_id,
 840};
 841
 842module_i2c_driver(au8522_driver);
 843