1e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/*
2e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * wm8739
3e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz *
4e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com>
5e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz *
6e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
7e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * - Cleanup
8898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz *
9e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * This program is free software; you can redistribute it and/or modify
10e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * it under the terms of the GNU General Public License as published by
1122aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz * the Free Software Foundation; either version 2 of the License, or
12e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * (at your option) any later version.
13e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz *
14e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * This program is distributed in the hope that it will be useful,
15e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * but WITHOUT ANY WARRANTY; without even the implied warranty of
16e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * GNU General Public License for more details.
18e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz *
1922aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz * You should have received a copy of the GNU General Public License
20e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * along with this program; if not, write to the Free Software
21e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2222aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz */
23e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
24e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <linux/module.h>
25e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <linux/types.h>
26e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <linux/slab.h>
27e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <linux/ioctl.h>
28e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <asm/uaccess.h>
29e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <linux/i2c.h>
30e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <linux/videodev2.h>
31e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <media/v4l2-device.h>
32e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <media/v4l2-chip-ident.h>
33e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz#include <media/v4l2-ctrls.h>
34e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
35e2984c628c924442132304ae662da433f41c05c9Bartlomiej ZolnierkiewiczMODULE_DESCRIPTION("wm8739 driver");
36e2984c628c924442132304ae662da433f41c05c9Bartlomiej ZolnierkiewiczMODULE_AUTHOR("T. Adachi, Hans Verkuil");
37e2984c628c924442132304ae662da433f41c05c9Bartlomiej ZolnierkiewiczMODULE_LICENSE("GPL");
38e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
39e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic int debug;
40e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
41e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczmodule_param(debug, int, 0644);
42898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz
43e2984c628c924442132304ae662da433f41c05c9Bartlomiej ZolnierkiewiczMODULE_PARM_DESC(debug, "Debug level (0-1)");
44e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
4522aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz
46e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/* ------------------------------------------------------------------------ */
47e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
48e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczenum {
49e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	R0 = 0, R1,
50e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	R5 = 5, R6, R7, R8, R9, R15 = 15,
51e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	TOT_REGS
52e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz};
53e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
54e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstruct wm8739_state {
55e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct v4l2_subdev sd;
56e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct v4l2_ctrl_handler hdl;
5722aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz	struct {
58e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		/* audio cluster */
59e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		struct v4l2_ctrl *volume;
60e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		struct v4l2_ctrl *mute;
6122aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz		struct v4l2_ctrl *balance;
62e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	};
63e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	u32 clock_freq;
64e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz};
65e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
66e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic inline struct wm8739_state *to_state(struct v4l2_subdev *sd)
67e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
68e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	return container_of(sd, struct wm8739_state, sd);
69e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz}
707f3c868ba78e486bd9d7569f884dd46d8f59bb18Bartlomiej Zolnierkiewicz
71e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
72e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
73e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	return &container_of(ctrl->handler, struct wm8739_state, hdl)->sd;
74e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz}
75e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
76e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/* ------------------------------------------------------------------------ */
77e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
78e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val)
79e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
80e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct i2c_client *client = v4l2_get_subdevdata(sd);
81e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	int i;
82e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
83e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	if (reg < 0 || reg >= TOT_REGS) {
84e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		v4l2_err(sd, "Invalid register R%d\n", reg);
85e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		return -1;
86e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	}
87e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
88e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	v4l2_dbg(1, debug, sd, "write: %02x %02x\n", reg, val);
89e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
90e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	for (i = 0; i < 3; i++)
91e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		if (i2c_smbus_write_byte_data(client,
92e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz				(reg << 1) | (val >> 8), val & 0xff) == 0)
93e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz			return 0;
94e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
95e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	return -1;
96e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz}
97e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
98e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic int wm8739_s_ctrl(struct v4l2_ctrl *ctrl)
99e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
100e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct v4l2_subdev *sd = to_sd(ctrl);
101e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct wm8739_state *state = to_state(sd);
102e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	unsigned int work_l, work_r;
103e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	u8 vol_l;	/* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
104e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	u8 vol_r;	/* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
105e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	u16 mute;
106e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
107e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	switch (ctrl->id) {
108e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	case V4L2_CID_AUDIO_VOLUME:
109e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		break;
110e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
111e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	default:
11222aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz		return -EINVAL;
113e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	}
11422aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz
115e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	/* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
116e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	work_l = (min(65536 - state->balance->val, 32768) * state->volume->val) / 32768;
117e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	work_r = (min(state->balance->val, 32768) * state->volume->val) / 32768;
118e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
119e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	vol_l = (long)work_l * 31 / 65535;
120e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	vol_r = (long)work_r * 31 / 65535;
121e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
122e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	/* set audio volume etc. */
123e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	mute = state->mute->val ? 0x80 : 0;
124e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
125e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	/* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
126e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	 * Default setting: 0x17 = 0 dB
12722aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz	 */
128e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	wm8739_write(sd, R0, (vol_l & 0x1f) | mute);
12922aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz	wm8739_write(sd, R1, (vol_r & 0x1f) | mute);
130e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	return 0;
131e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz}
13222aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz
133e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/* ------------------------------------------------------------------------ */
134e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
135e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq)
136e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
137e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct wm8739_state *state = to_state(sd);
138e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
139e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	state->clock_freq = audiofreq;
140e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	/* de-activate */
141e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	wm8739_write(sd, R9, 0x000);
142e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	switch (audiofreq) {
143e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	case 44100:
144e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		/* 256fps, fs=44.1k */
14522aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz		wm8739_write(sd, R8, 0x020);
146e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		break;
147e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	case 48000:
148e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		/* 256fps, fs=48k */
149e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		wm8739_write(sd, R8, 0x000);
150e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		break;
151e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	case 32000:
152e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		/* 256fps, fs=32k */
153e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		wm8739_write(sd, R8, 0x018);
154e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		break;
155e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	default:
156e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		break;
157e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	}
158e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	/* activate */
159e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	wm8739_write(sd, R9, 0x001);
160e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	return 0;
161e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz}
162e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
16322aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewiczstatic int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
164e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
165e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct i2c_client *client = v4l2_get_subdevdata(sd);
166e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
16722aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8739, 0);
16822aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz}
16922aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz
17022aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewiczstatic int wm8739_log_status(struct v4l2_subdev *sd)
171e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
172e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct wm8739_state *state = to_state(sd);
173e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
1743616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewicz	v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq);
175e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
176e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	return 0;
177e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz}
178e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
179e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/* ----------------------------------------------------------------------- */
180e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
1813616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewiczstatic const struct v4l2_ctrl_ops wm8739_ctrl_ops = {
182e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.s_ctrl = wm8739_s_ctrl,
183e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz};
1843616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewicz
185e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic const struct v4l2_subdev_core_ops wm8739_core_ops = {
186e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.log_status = wm8739_log_status,
1873616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewicz	.g_chip_ident = wm8739_g_chip_ident,
1883616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewicz	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1893616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewicz	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1903616b6536a74ff1c56029c17cbb3575c69c0a574Bartlomiej Zolnierkiewicz	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
191e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.g_ctrl = v4l2_subdev_g_ctrl,
192e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.s_ctrl = v4l2_subdev_s_ctrl,
193e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.queryctrl = v4l2_subdev_queryctrl,
194e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.querymenu = v4l2_subdev_querymenu,
195e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz};
1962ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz
197e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic const struct v4l2_subdev_audio_ops wm8739_audio_ops = {
1982ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz	.s_clock_freq = wm8739_s_clock_freq,
199e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz};
200e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
201e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic const struct v4l2_subdev_ops wm8739_ops = {
202b65fac32cfe3b2f98cd472fef400bd1c1340de23Bartlomiej Zolnierkiewicz	.core = &wm8739_core_ops,
203e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	.audio = &wm8739_audio_ops,
204e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz};
205e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
206e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/* ------------------------------------------------------------------------ */
207e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
208e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz/* i2c implementation */
209e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
210e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewiczstatic int wm8739_probe(struct i2c_client *client,
211e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz			const struct i2c_device_id *id)
212e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz{
213e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct wm8739_state *state;
214e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	struct v4l2_subdev *sd;
215e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
216e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	/* Check if the adapter supports the needed features */
217e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
218e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		return -EIO;
219e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
220e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	v4l_info(client, "chip found @ 0x%x (%s)\n",
221e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz			client->addr << 1, client->adapter->name);
222e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
223e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	state = kzalloc(sizeof(struct wm8739_state), GFP_KERNEL);
224e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	if (state == NULL)
225e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		return -ENOMEM;
226e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	sd = &state->sd;
2272ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz	v4l2_i2c_subdev_init(sd, client, &wm8739_ops);
2282ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz	v4l2_ctrl_handler_init(&state->hdl, 2);
229e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	state->volume = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
230e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 50736);
231e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
232e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
233e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	state->balance = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
234e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
235e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	sd->ctrl_handler = &state->hdl;
236e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	if (state->hdl.error) {
237e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		int err = state->hdl.error;
238e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
239e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		v4l2_ctrl_handler_free(&state->hdl);
240e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz		kfree(state);
2412ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz		return err;
2422ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz	}
2432ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz	v4l2_ctrl_cluster(3, &state->volume);
2442ea5521022ac8f4f528dcbae02668e02a3501a5aBartlomiej Zolnierkiewicz
245e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz	state->clock_freq = 48000;
246e2984c628c924442132304ae662da433f41c05c9Bartlomiej Zolnierkiewicz
247	/* Initialize wm8739 */
248
249	/* reset */
250	wm8739_write(sd, R15, 0x00);
251	/* filter setting, high path, offet clear */
252	wm8739_write(sd, R5, 0x000);
253	/* ADC, OSC, Power Off mode Disable */
254	wm8739_write(sd, R6, 0x000);
255	/* Digital Audio interface format:
256	   Enable Master mode, 24 bit, MSB first/left justified */
257	wm8739_write(sd, R7, 0x049);
258	/* sampling control: normal, 256fs, 48KHz sampling rate */
259	wm8739_write(sd, R8, 0x000);
260	/* activate */
261	wm8739_write(sd, R9, 0x001);
262	/* set volume/mute */
263	v4l2_ctrl_handler_setup(&state->hdl);
264	return 0;
265}
266
267static int wm8739_remove(struct i2c_client *client)
268{
269	struct v4l2_subdev *sd = i2c_get_clientdata(client);
270	struct wm8739_state *state = to_state(sd);
271
272	v4l2_device_unregister_subdev(sd);
273	v4l2_ctrl_handler_free(&state->hdl);
274	kfree(to_state(sd));
275	return 0;
276}
277
278static const struct i2c_device_id wm8739_id[] = {
279	{ "wm8739", 0 },
280	{ }
281};
282MODULE_DEVICE_TABLE(i2c, wm8739_id);
283
284static struct i2c_driver wm8739_driver = {
285	.driver = {
286		.owner	= THIS_MODULE,
287		.name	= "wm8739",
288	},
289	.probe		= wm8739_probe,
290	.remove		= wm8739_remove,
291	.id_table	= wm8739_id,
292};
293
294static __init int init_wm8739(void)
295{
296	return i2c_add_driver(&wm8739_driver);
297}
298
299static __exit void exit_wm8739(void)
300{
301	i2c_del_driver(&wm8739_driver);
302}
303
304module_init(init_wm8739);
305module_exit(exit_wm8739);
306