19db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim/*
29db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim * max9877.c  --  amp driver for max9877
39db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *
49db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim * Copyright (C) 2009 Samsung Electronics Co.Ltd
59db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim * Author: Joonyoung Shim <jy0922.shim@samsung.com>
69db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *
79db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *  This program is free software; you can redistribute  it and/or modify it
89db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *  under  the terms of  the GNU General  Public License as published by the
99db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *  Free Software Foundation;  either version 2 of the  License, or (at your
109db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *  option) any later version.
119db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim *
129db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim */
139db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
149db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim#include <linux/module.h>
159db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim#include <linux/init.h>
169db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim#include <linux/i2c.h>
179db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim#include <sound/soc.h>
189db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim#include <sound/tlv.h>
199db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
209db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim#include "max9877.h"
219db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
229db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic struct i2c_client *i2c;
239db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
249db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 };
259db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
269db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic void max9877_write_regs(void)
279db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
28a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	unsigned int i;
29a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	u8 data[6];
30a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim
31a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	data[0] = MAX9877_INPUT_MODE;
32a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
33a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim		data[i + 1] = max9877_regs[i];
34a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim
35a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	if (i2c_master_send(i2c, data, 6) != 6)
369db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		dev_err(&i2c->dev, "i2c write failed\n");
379db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
389db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
399db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int max9877_get_reg(struct snd_kcontrol *kcontrol,
409db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		struct snd_ctl_elem_value *ucontrol)
419db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
429db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	struct soc_mixer_control *mc =
439db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		(struct soc_mixer_control *)kcontrol->private_value;
44e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int reg = mc->reg;
45e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int shift = mc->shift;
46e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int mask = mc->max;
47e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int invert = mc->invert;
489db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
499db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
509db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
51e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	if (invert)
52e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		ucontrol->value.integer.value[0] =
53e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim			mask - ucontrol->value.integer.value[0];
549db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
559db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 0;
569db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
579db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
589db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int max9877_set_reg(struct snd_kcontrol *kcontrol,
599db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		struct snd_ctl_elem_value *ucontrol)
609db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
619db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	struct soc_mixer_control *mc =
629db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		(struct soc_mixer_control *)kcontrol->private_value;
63e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int reg = mc->reg;
64e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int shift = mc->shift;
65e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int mask = mc->max;
66e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int invert = mc->invert;
67e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int val = (ucontrol->value.integer.value[0] & mask);
68e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
69e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	if (invert)
70e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		val = mask - val;
71e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
72e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	if (((max9877_regs[reg] >> shift) & mask) == val)
73e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		return 0;
74e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
75e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	max9877_regs[reg] &= ~(mask << shift);
76e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	max9877_regs[reg] |= val << shift;
77e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	max9877_write_regs();
78e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
79e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	return 1;
80e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim}
81e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
82e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shimstatic int max9877_get_2reg(struct snd_kcontrol *kcontrol,
83e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		struct snd_ctl_elem_value *ucontrol)
84e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim{
85e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	struct soc_mixer_control *mc =
86e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		(struct soc_mixer_control *)kcontrol->private_value;
87e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int reg = mc->reg;
88e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int reg2 = mc->rreg;
89e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int shift = mc->shift;
90e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int mask = mc->max;
91e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
92e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
93e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
94e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
95e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	return 0;
96e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim}
97e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
98e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shimstatic int max9877_set_2reg(struct snd_kcontrol *kcontrol,
99e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		struct snd_ctl_elem_value *ucontrol)
100e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim{
101e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	struct soc_mixer_control *mc =
102e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		(struct soc_mixer_control *)kcontrol->private_value;
103e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int reg = mc->reg;
104e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int reg2 = mc->rreg;
105e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int shift = mc->shift;
106e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int mask = mc->max;
107e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int val = (ucontrol->value.integer.value[0] & mask);
108e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
109e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	unsigned int change = 1;
110e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim
111e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	if (((max9877_regs[reg] >> shift) & mask) == val)
1129db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		change = 0;
1139db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
114e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	if (((max9877_regs[reg2] >> shift) & mask) == val2)
115e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		change = 0;
1169db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1179db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	if (change) {
1189db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		max9877_regs[reg] &= ~(mask << shift);
119e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		max9877_regs[reg] |= val << shift;
1209db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		max9877_regs[reg2] &= ~(mask << shift);
121e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim		max9877_regs[reg2] |= val2 << shift;
1229db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		max9877_write_regs();
123e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	}
1249db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
125e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim	return change;
1269db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
1279db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1289db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
1299db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		struct snd_ctl_elem_value *ucontrol)
1309db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
1319db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
1329db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1339db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	if (value)
1349db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		value -= 1;
1359db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1369db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	ucontrol->value.integer.value[0] = value;
1379db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 0;
1389db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
1399db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1409db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
1419db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		struct snd_ctl_elem_value *ucontrol)
1429db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
1439db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	u8 value = ucontrol->value.integer.value[0];
1449db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
145a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	value += 1;
1469db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1479db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
1489db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		return 0;
1499db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
150a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK;
1519db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	max9877_regs[MAX9877_OUTPUT_MODE] |= value;
1529db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	max9877_write_regs();
1539db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 1;
1549db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
1559db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1569db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
1579db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		struct snd_ctl_elem_value *ucontrol)
1589db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
1599db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
1609db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1619db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	value = value >> MAX9877_OSC_OFFSET;
1629db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1639db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	ucontrol->value.integer.value[0] = value;
1649db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 0;
1659db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
1669db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1679db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
1689db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		struct snd_ctl_elem_value *ucontrol)
1699db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
1709db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	u8 value = ucontrol->value.integer.value[0];
1719db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1729db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	value = value << MAX9877_OSC_OFFSET;
1739db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
1749db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		return 0;
1759db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
176a7569afa8b79ca9272b0d7544335bc05b5b721d6Joonyoung Shim	max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK;
1779db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	max9877_regs[MAX9877_OUTPUT_MODE] |= value;
1789db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	max9877_write_regs();
1799db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 1;
1809db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
1819db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1829db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const unsigned int max9877_pgain_tlv[] = {
1839db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	TLV_DB_RANGE_HEAD(2),
1849db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	0, 1, TLV_DB_SCALE_ITEM(0, 900, 0),
1859db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
1869db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
1879db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1889db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const unsigned int max9877_output_tlv[] = {
1899db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	TLV_DB_RANGE_HEAD(4),
1909db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
1919db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
1929db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
1939db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
1949db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
1959db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
1969db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const char *max9877_out_mode[] = {
1979db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INA -> SPK",
1989db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INA -> HP",
1999db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INA -> SPK and HP",
2009db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INB -> SPK",
2019db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INB -> HP",
2029db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INB -> SPK and HP",
2039db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INA + INB -> SPK",
2049db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INA + INB -> HP",
2059db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"INA + INB -> SPK and HP",
2069db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
2079db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2089db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const char *max9877_osc_mode[] = {
2099db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"1176KHz",
2109db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"1100KHz",
2119db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	"700KHz",
2129db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
2139db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2149db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const struct soc_enum max9877_enum[] = {
2159db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode),
2169db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
2179db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
2189db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2199db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const struct snd_kcontrol_new max9877_controls[] = {
2209db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume",
2219db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_INPUT_MODE, 0, 2, 0,
2229db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
2239db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume",
2249db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_INPUT_MODE, 2, 2, 0,
2259db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
2269db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume",
2279db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_SPK_VOLUME, 0, 31, 0,
2289db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg, max9877_output_tlv),
2299db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume",
2309db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
231e458a48f8776d624d05246471501c6086adb1d7aJoonyoung Shim			max9877_get_2reg, max9877_set_2reg, max9877_output_tlv),
2329db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT("MAX9877 INB Stereo Switch",
2339db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_INPUT_MODE, 4, 1, 1,
2349db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg),
2359db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT("MAX9877 INA Stereo Switch",
2369db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_INPUT_MODE, 5, 1, 1,
2379db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg),
2389db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch",
2399db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_INPUT_MODE, 6, 1, 0,
2409db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg),
2419db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
2429db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_OUTPUT_MODE, 6, 1, 0,
2439db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg),
2449db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
2459db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			MAX9877_OUTPUT_MODE, 7, 1, 1,
2469db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_reg, max9877_set_reg),
2479db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
2489db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_out_mode, max9877_set_out_mode),
2499db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
2509db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			max9877_get_osc_mode, max9877_set_osc_mode),
2519db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
2529db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2539db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim/* This function is called from ASoC machine driver */
2549db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimint max9877_add_controls(struct snd_soc_codec *codec)
2559db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
2569db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return snd_soc_add_controls(codec, max9877_controls,
2579db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim			ARRAY_SIZE(max9877_controls));
2589db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
2599db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung ShimEXPORT_SYMBOL_GPL(max9877_add_controls);
2609db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2619db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int __devinit max9877_i2c_probe(struct i2c_client *client,
2629db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		const struct i2c_device_id *id)
2639db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
2649db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	i2c = client;
2659db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2669db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	max9877_write_regs();
2679db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2689db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 0;
2699db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
2709db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2719db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic __devexit int max9877_i2c_remove(struct i2c_client *client)
2729db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
2739db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	i2c = NULL;
2749db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2759db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return 0;
2769db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
2779db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2789db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic const struct i2c_device_id max9877_i2c_id[] = {
2799db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	{ "max9877", 0 },
2809db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	{ }
2819db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
2829db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung ShimMODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
2839db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2849db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic struct i2c_driver max9877_i2c_driver = {
2859db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	.driver = {
2869db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		.name = "max9877",
2879db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim		.owner = THIS_MODULE,
2889db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	},
2899db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	.probe = max9877_i2c_probe,
2909db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	.remove = __devexit_p(max9877_i2c_remove),
2919db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	.id_table = max9877_i2c_id,
2929db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim};
2939db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
2949db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic int __init max9877_init(void)
2959db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
2969db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	return i2c_add_driver(&max9877_i2c_driver);
2979db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
2989db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimmodule_init(max9877_init);
2999db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
3009db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimstatic void __exit max9877_exit(void)
3019db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim{
3029db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim	i2c_del_driver(&max9877_i2c_driver);
3039db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim}
3049db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shimmodule_exit(max9877_exit);
3059db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung Shim
3069db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung ShimMODULE_DESCRIPTION("ASoC MAX9877 amp driver");
3079db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung ShimMODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
3089db9ed977d4f1a317f5f4d467d43025fa27223d8Joonyoung ShimMODULE_LICENSE("GPL");
309