linux/drivers/media/i2c/cs53l32a.c
<<
>>
Prefs
   1/*
   2 * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver.
   3 * Copyright (C) 2005  Martin Vaughan
   4 *
   5 * Audio source switching for Adaptec AVC-2410 added by Trev Jackson
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 */
  21
  22
  23#include <linux/module.h>
  24#include <linux/types.h>
  25#include <linux/slab.h>
  26#include <linux/ioctl.h>
  27#include <asm/uaccess.h>
  28#include <linux/i2c.h>
  29#include <linux/videodev2.h>
  30#include <media/v4l2-device.h>
  31#include <media/v4l2-chip-ident.h>
  32#include <media/v4l2-ctrls.h>
  33
  34MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
  35MODULE_AUTHOR("Martin Vaughan");
  36MODULE_LICENSE("GPL");
  37
  38static bool debug;
  39
  40module_param(debug, bool, 0644);
  41
  42MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
  43
  44
  45struct cs53l32a_state {
  46        struct v4l2_subdev sd;
  47        struct v4l2_ctrl_handler hdl;
  48};
  49
  50static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
  51{
  52        return container_of(sd, struct cs53l32a_state, sd);
  53}
  54
  55static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  56{
  57        return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
  58}
  59
  60/* ----------------------------------------------------------------------- */
  61
  62static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
  63{
  64        struct i2c_client *client = v4l2_get_subdevdata(sd);
  65
  66        return i2c_smbus_write_byte_data(client, reg, value);
  67}
  68
  69static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg)
  70{
  71        struct i2c_client *client = v4l2_get_subdevdata(sd);
  72
  73        return i2c_smbus_read_byte_data(client, reg);
  74}
  75
  76static int cs53l32a_s_routing(struct v4l2_subdev *sd,
  77                              u32 input, u32 output, u32 config)
  78{
  79        /* There are 2 physical inputs, but the second input can be
  80           placed in two modes, the first mode bypasses the PGA (gain),
  81           the second goes through the PGA. Hence there are three
  82           possible inputs to choose from. */
  83        if (input > 2) {
  84                v4l2_err(sd, "Invalid input %d.\n", input);
  85                return -EINVAL;
  86        }
  87        cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
  88        return 0;
  89}
  90
  91static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
  92{
  93        struct v4l2_subdev *sd = to_sd(ctrl);
  94
  95        switch (ctrl->id) {
  96        case V4L2_CID_AUDIO_MUTE:
  97                cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
  98                return 0;
  99        case V4L2_CID_AUDIO_VOLUME:
 100                cs53l32a_write(sd, 0x04, (u8)ctrl->val);
 101                cs53l32a_write(sd, 0x05, (u8)ctrl->val);
 102                return 0;
 103        }
 104        return -EINVAL;
 105}
 106
 107static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 108{
 109        struct i2c_client *client = v4l2_get_subdevdata(sd);
 110
 111        return v4l2_chip_ident_i2c_client(client,
 112                        chip, V4L2_IDENT_CS53l32A, 0);
 113}
 114
 115static int cs53l32a_log_status(struct v4l2_subdev *sd)
 116{
 117        struct cs53l32a_state *state = to_state(sd);
 118        u8 v = cs53l32a_read(sd, 0x01);
 119
 120        v4l2_info(sd, "Input:  %d\n", (v >> 4) & 3);
 121        v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
 122        return 0;
 123}
 124
 125/* ----------------------------------------------------------------------- */
 126
 127static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
 128        .s_ctrl = cs53l32a_s_ctrl,
 129};
 130
 131static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
 132        .log_status = cs53l32a_log_status,
 133        .g_chip_ident = cs53l32a_g_chip_ident,
 134        .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
 135        .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
 136        .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
 137        .g_ctrl = v4l2_subdev_g_ctrl,
 138        .s_ctrl = v4l2_subdev_s_ctrl,
 139        .queryctrl = v4l2_subdev_queryctrl,
 140        .querymenu = v4l2_subdev_querymenu,
 141};
 142
 143static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
 144        .s_routing = cs53l32a_s_routing,
 145};
 146
 147static const struct v4l2_subdev_ops cs53l32a_ops = {
 148        .core = &cs53l32a_core_ops,
 149        .audio = &cs53l32a_audio_ops,
 150};
 151
 152/* ----------------------------------------------------------------------- */
 153
 154/* i2c implementation */
 155
 156/*
 157 * Generic i2c probe
 158 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
 159 */
 160
 161static int cs53l32a_probe(struct i2c_client *client,
 162                          const struct i2c_device_id *id)
 163{
 164        struct cs53l32a_state *state;
 165        struct v4l2_subdev *sd;
 166        int i;
 167
 168        /* Check if the adapter supports the needed features */
 169        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 170                return -EIO;
 171
 172        if (!id)
 173                strlcpy(client->name, "cs53l32a", sizeof(client->name));
 174
 175        v4l_info(client, "chip found @ 0x%x (%s)\n",
 176                        client->addr << 1, client->adapter->name);
 177
 178        state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL);
 179        if (state == NULL)
 180                return -ENOMEM;
 181        sd = &state->sd;
 182        v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
 183
 184        for (i = 1; i <= 7; i++) {
 185                u8 v = cs53l32a_read(sd, i);
 186
 187                v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
 188        }
 189
 190        v4l2_ctrl_handler_init(&state->hdl, 2);
 191        v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
 192                        V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
 193        v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
 194                        V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
 195        sd->ctrl_handler = &state->hdl;
 196        if (state->hdl.error) {
 197                int err = state->hdl.error;
 198
 199                v4l2_ctrl_handler_free(&state->hdl);
 200                kfree(state);
 201                return err;
 202        }
 203
 204        /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
 205
 206        cs53l32a_write(sd, 0x01, 0x21);
 207        cs53l32a_write(sd, 0x02, 0x29);
 208        cs53l32a_write(sd, 0x03, 0x30);
 209        cs53l32a_write(sd, 0x04, 0x00);
 210        cs53l32a_write(sd, 0x05, 0x00);
 211        cs53l32a_write(sd, 0x06, 0x00);
 212        cs53l32a_write(sd, 0x07, 0x00);
 213
 214        /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
 215
 216        for (i = 1; i <= 7; i++) {
 217                u8 v = cs53l32a_read(sd, i);
 218
 219                v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
 220        }
 221        return 0;
 222}
 223
 224static int cs53l32a_remove(struct i2c_client *client)
 225{
 226        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 227        struct cs53l32a_state *state = to_state(sd);
 228
 229        v4l2_device_unregister_subdev(sd);
 230        v4l2_ctrl_handler_free(&state->hdl);
 231        kfree(state);
 232        return 0;
 233}
 234
 235static const struct i2c_device_id cs53l32a_id[] = {
 236        { "cs53l32a", 0 },
 237        { }
 238};
 239MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
 240
 241static struct i2c_driver cs53l32a_driver = {
 242        .driver = {
 243                .owner  = THIS_MODULE,
 244                .name   = "cs53l32a",
 245        },
 246        .probe          = cs53l32a_probe,
 247        .remove         = cs53l32a_remove,
 248        .id_table       = cs53l32a_id,
 249};
 250
 251module_i2c_driver(cs53l32a_driver);
 252