linux/drivers/media/i2c/wm8739.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * wm8739
   4 *
   5 * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com>
   6 *
   7 * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
   8 * - Cleanup
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/types.h>
  13#include <linux/slab.h>
  14#include <linux/ioctl.h>
  15#include <linux/uaccess.h>
  16#include <linux/i2c.h>
  17#include <linux/videodev2.h>
  18#include <media/v4l2-device.h>
  19#include <media/v4l2-ctrls.h>
  20
  21MODULE_DESCRIPTION("wm8739 driver");
  22MODULE_AUTHOR("T. Adachi, Hans Verkuil");
  23MODULE_LICENSE("GPL");
  24
  25static int debug;
  26
  27module_param(debug, int, 0644);
  28
  29MODULE_PARM_DESC(debug, "Debug level (0-1)");
  30
  31
  32/* ------------------------------------------------------------------------ */
  33
  34enum {
  35        R0 = 0, R1,
  36        R5 = 5, R6, R7, R8, R9, R15 = 15,
  37        TOT_REGS
  38};
  39
  40struct wm8739_state {
  41        struct v4l2_subdev sd;
  42        struct v4l2_ctrl_handler hdl;
  43        struct {
  44                /* audio cluster */
  45                struct v4l2_ctrl *volume;
  46                struct v4l2_ctrl *mute;
  47                struct v4l2_ctrl *balance;
  48        };
  49        u32 clock_freq;
  50};
  51
  52static inline struct wm8739_state *to_state(struct v4l2_subdev *sd)
  53{
  54        return container_of(sd, struct wm8739_state, sd);
  55}
  56
  57static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  58{
  59        return &container_of(ctrl->handler, struct wm8739_state, hdl)->sd;
  60}
  61
  62/* ------------------------------------------------------------------------ */
  63
  64static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val)
  65{
  66        struct i2c_client *client = v4l2_get_subdevdata(sd);
  67        int i;
  68
  69        if (reg < 0 || reg >= TOT_REGS) {
  70                v4l2_err(sd, "Invalid register R%d\n", reg);
  71                return -1;
  72        }
  73
  74        v4l2_dbg(1, debug, sd, "write: %02x %02x\n", reg, val);
  75
  76        for (i = 0; i < 3; i++)
  77                if (i2c_smbus_write_byte_data(client,
  78                                (reg << 1) | (val >> 8), val & 0xff) == 0)
  79                        return 0;
  80        v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
  81        return -1;
  82}
  83
  84static int wm8739_s_ctrl(struct v4l2_ctrl *ctrl)
  85{
  86        struct v4l2_subdev *sd = to_sd(ctrl);
  87        struct wm8739_state *state = to_state(sd);
  88        unsigned int work_l, work_r;
  89        u8 vol_l;       /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
  90        u8 vol_r;       /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
  91        u16 mute;
  92
  93        switch (ctrl->id) {
  94        case V4L2_CID_AUDIO_VOLUME:
  95                break;
  96
  97        default:
  98                return -EINVAL;
  99        }
 100
 101        /* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
 102        work_l = (min(65536 - state->balance->val, 32768) * state->volume->val) / 32768;
 103        work_r = (min(state->balance->val, 32768) * state->volume->val) / 32768;
 104
 105        vol_l = (long)work_l * 31 / 65535;
 106        vol_r = (long)work_r * 31 / 65535;
 107
 108        /* set audio volume etc. */
 109        mute = state->mute->val ? 0x80 : 0;
 110
 111        /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
 112         * Default setting: 0x17 = 0 dB
 113         */
 114        wm8739_write(sd, R0, (vol_l & 0x1f) | mute);
 115        wm8739_write(sd, R1, (vol_r & 0x1f) | mute);
 116        return 0;
 117}
 118
 119/* ------------------------------------------------------------------------ */
 120
 121static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq)
 122{
 123        struct wm8739_state *state = to_state(sd);
 124
 125        state->clock_freq = audiofreq;
 126        /* de-activate */
 127        wm8739_write(sd, R9, 0x000);
 128        switch (audiofreq) {
 129        case 44100:
 130                /* 256fps, fs=44.1k */
 131                wm8739_write(sd, R8, 0x020);
 132                break;
 133        case 48000:
 134                /* 256fps, fs=48k */
 135                wm8739_write(sd, R8, 0x000);
 136                break;
 137        case 32000:
 138                /* 256fps, fs=32k */
 139                wm8739_write(sd, R8, 0x018);
 140                break;
 141        default:
 142                break;
 143        }
 144        /* activate */
 145        wm8739_write(sd, R9, 0x001);
 146        return 0;
 147}
 148
 149static int wm8739_log_status(struct v4l2_subdev *sd)
 150{
 151        struct wm8739_state *state = to_state(sd);
 152
 153        v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq);
 154        v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
 155        return 0;
 156}
 157
 158/* ----------------------------------------------------------------------- */
 159
 160static const struct v4l2_ctrl_ops wm8739_ctrl_ops = {
 161        .s_ctrl = wm8739_s_ctrl,
 162};
 163
 164static const struct v4l2_subdev_core_ops wm8739_core_ops = {
 165        .log_status = wm8739_log_status,
 166};
 167
 168static const struct v4l2_subdev_audio_ops wm8739_audio_ops = {
 169        .s_clock_freq = wm8739_s_clock_freq,
 170};
 171
 172static const struct v4l2_subdev_ops wm8739_ops = {
 173        .core = &wm8739_core_ops,
 174        .audio = &wm8739_audio_ops,
 175};
 176
 177/* ------------------------------------------------------------------------ */
 178
 179/* i2c implementation */
 180
 181static int wm8739_probe(struct i2c_client *client,
 182                        const struct i2c_device_id *id)
 183{
 184        struct wm8739_state *state;
 185        struct v4l2_subdev *sd;
 186
 187        /* Check if the adapter supports the needed features */
 188        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 189                return -EIO;
 190
 191        v4l_info(client, "chip found @ 0x%x (%s)\n",
 192                        client->addr << 1, client->adapter->name);
 193
 194        state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
 195        if (state == NULL)
 196                return -ENOMEM;
 197        sd = &state->sd;
 198        v4l2_i2c_subdev_init(sd, client, &wm8739_ops);
 199        v4l2_ctrl_handler_init(&state->hdl, 2);
 200        state->volume = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
 201                        V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 50736);
 202        state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
 203                        V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
 204        state->balance = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
 205                        V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
 206        sd->ctrl_handler = &state->hdl;
 207        if (state->hdl.error) {
 208                int err = state->hdl.error;
 209
 210                v4l2_ctrl_handler_free(&state->hdl);
 211                return err;
 212        }
 213        v4l2_ctrl_cluster(3, &state->volume);
 214
 215        state->clock_freq = 48000;
 216
 217        /* Initialize wm8739 */
 218
 219        /* reset */
 220        wm8739_write(sd, R15, 0x00);
 221        /* filter setting, high path, offet clear */
 222        wm8739_write(sd, R5, 0x000);
 223        /* ADC, OSC, Power Off mode Disable */
 224        wm8739_write(sd, R6, 0x000);
 225        /* Digital Audio interface format:
 226           Enable Master mode, 24 bit, MSB first/left justified */
 227        wm8739_write(sd, R7, 0x049);
 228        /* sampling control: normal, 256fs, 48KHz sampling rate */
 229        wm8739_write(sd, R8, 0x000);
 230        /* activate */
 231        wm8739_write(sd, R9, 0x001);
 232        /* set volume/mute */
 233        v4l2_ctrl_handler_setup(&state->hdl);
 234        return 0;
 235}
 236
 237static int wm8739_remove(struct i2c_client *client)
 238{
 239        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 240        struct wm8739_state *state = to_state(sd);
 241
 242        v4l2_device_unregister_subdev(sd);
 243        v4l2_ctrl_handler_free(&state->hdl);
 244        return 0;
 245}
 246
 247static const struct i2c_device_id wm8739_id[] = {
 248        { "wm8739", 0 },
 249        { }
 250};
 251MODULE_DEVICE_TABLE(i2c, wm8739_id);
 252
 253static struct i2c_driver wm8739_driver = {
 254        .driver = {
 255                .name   = "wm8739",
 256        },
 257        .probe          = wm8739_probe,
 258        .remove         = wm8739_remove,
 259        .id_table       = wm8739_id,
 260};
 261
 262module_i2c_driver(wm8739_driver);
 263