Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 306172
b: refs/heads/master
c: b31506c
h: refs/heads/master
v: v3
  • Loading branch information
Michael Krufky authored and Mauro Carvalho Chehab committed Apr 19, 2012
1 parent 3dbf7a8 commit 88c43f0
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 223 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: be183dc3f73d7e8e0091c54fc3fa04d9ccb91903
refs/heads/master: b31506c47c5ae67a82fa72e6d763a8f34413aac8
22 changes: 18 additions & 4 deletions trunk/drivers/media/dvb/frontends/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,26 @@ config DVB_S5H1409
to support this frontend.

config DVB_AU8522
tristate "Auvitek AU8522 based"
depends on DVB_CORE && I2C && VIDEO_V4L2
depends on I2C
tristate

config DVB_AU8522_DTV
tristate "Auvitek AU8522 based DTV demod"
depends on DVB_CORE && I2C
select DVB_AU8522
default m if DVB_FE_CUSTOMISE
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
you want to enable DTV demodulation support for this frontend.

config DVB_AU8522_V4L
tristate "Auvitek AU8522 based ATV demod"
depends on VIDEO_V4L2 && I2C
select DVB_AU8522
default m if DVB_FE_CUSTOMISE
help
An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
you want to enable ATV demodulation support for this frontend.

config DVB_S5H1411
tristate "Samsung S5H1411 based"
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/media/dvb/frontends/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ ccflags-y += -I$(srctree)/drivers/media/common/tuners/

stb0899-objs = stb0899_drv.o stb0899_algo.o
stv0900-objs = stv0900_core.o stv0900_sw.o
au8522-objs = au8522_dig.o au8522_decoder.o
drxd-objs = drxd_firm.o drxd_hard.o
cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
drxk-objs := drxk_hard.o
Expand Down Expand Up @@ -63,7 +62,9 @@ obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
obj-$(CONFIG_DVB_AU8522) += au8522.o
obj-$(CONFIG_DVB_AU8522) += au8522_common.o
obj-$(CONFIG_DVB_AU8522_DTV) += au8522_dig.o
obj-$(CONFIG_DVB_AU8522_V4L) += au8522_decoder.o
obj-$(CONFIG_DVB_TDA10048) += tda10048.o
obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
Expand Down
258 changes: 258 additions & 0 deletions trunk/drivers/media/dvb/frontends/au8522_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
/*
Auvitek AU8522 QAM/8VSB demodulator driver
Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
Copyright (C) 2008 Devin Heitmueller <dheitmueller@linuxtv.org>
Copyright (C) 2005-2008 Auvitek International, Ltd.
Copyright (C) 2012 Michael Krufky <mkrufky@linuxtv.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "au8522_priv.h"

static int debug;

#define dprintk(arg...)\
do { if (debug)\
printk(arg);\
} while (0)

/* Despite the name "hybrid_tuner", the framework works just as well for
hybrid demodulators as well... */
static LIST_HEAD(hybrid_tuner_instance_list);
static DEFINE_MUTEX(au8522_list_mutex);

/* 16 bit registers, 8 bit values */
int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
{
int ret;
u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };

struct i2c_msg msg = { .addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 3 };

ret = i2c_transfer(state->i2c, &msg, 1);

if (ret != 1)
printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
"ret == %i)\n", __func__, reg, data, ret);

return (ret != 1) ? -1 : 0;
}
EXPORT_SYMBOL(au8522_writereg);

u8 au8522_readreg(struct au8522_state *state, u16 reg)
{
int ret;
u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
u8 b1[] = { 0 };

struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0,
.buf = b0, .len = 2 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD,
.buf = b1, .len = 1 } };

ret = i2c_transfer(state->i2c, msg, 2);

if (ret != 2)
printk(KERN_ERR "%s: readreg error (ret == %i)\n",
__func__, ret);
return b1[0];
}
EXPORT_SYMBOL(au8522_readreg);

int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct au8522_state *state = fe->demodulator_priv;

dprintk("%s(%d)\n", __func__, enable);

if (state->operational_mode == AU8522_ANALOG_MODE) {
/* We're being asked to manage the gate even though we're
not in digital mode. This can occur if we get switched
over to analog mode before the dvb_frontend kernel thread
has completely shutdown */
return 0;
}

if (enable)
return au8522_writereg(state, 0x106, 1);
else
return au8522_writereg(state, 0x106, 0);
}
EXPORT_SYMBOL(au8522_i2c_gate_ctrl);

/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
u8 client_address)
{
int ret;

mutex_lock(&au8522_list_mutex);
ret = hybrid_tuner_request_state(struct au8522_state, (*state),
hybrid_tuner_instance_list,
i2c, client_address, "au8522");
mutex_unlock(&au8522_list_mutex);

return ret;
}
EXPORT_SYMBOL(au8522_get_state);

void au8522_release_state(struct au8522_state *state)
{
mutex_lock(&au8522_list_mutex);
if (state != NULL)
hybrid_tuner_release_state(state);
mutex_unlock(&au8522_list_mutex);
}
EXPORT_SYMBOL(au8522_release_state);

int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
{
struct au8522_led_config *led_config = state->config->led_cfg;
u8 val;

/* bail out if we can't control an LED */
if (!led_config || !led_config->gpio_output ||
!led_config->gpio_output_enable || !led_config->gpio_output_disable)
return 0;

val = au8522_readreg(state, 0x4000 |
(led_config->gpio_output & ~0xc000));
if (onoff) {
/* enable GPIO output */
val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
val |= (led_config->gpio_output_enable & 0xff);
} else {
/* disable GPIO output */
val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
val |= (led_config->gpio_output_disable & 0xff);
}
return au8522_writereg(state, 0x8000 |
(led_config->gpio_output & ~0xc000), val);
}
EXPORT_SYMBOL(au8522_led_gpio_enable);

/* led = 0 | off
* led = 1 | signal ok
* led = 2 | signal strong
* led < 0 | only light led if leds are currently off
*/
int au8522_led_ctrl(struct au8522_state *state, int led)
{
struct au8522_led_config *led_config = state->config->led_cfg;
int i, ret = 0;

/* bail out if we can't control an LED */
if (!led_config || !led_config->gpio_leds ||
!led_config->num_led_states || !led_config->led_states)
return 0;

if (led < 0) {
/* if LED is already lit, then leave it as-is */
if (state->led_state)
return 0;
else
led *= -1;
}

/* toggle LED if changing state */
if (state->led_state != led) {
u8 val;

dprintk("%s: %d\n", __func__, led);

au8522_led_gpio_enable(state, 1);

val = au8522_readreg(state, 0x4000 |
(led_config->gpio_leds & ~0xc000));

/* start with all leds off */
for (i = 0; i < led_config->num_led_states; i++)
val &= ~led_config->led_states[i];

/* set selected LED state */
if (led < led_config->num_led_states)
val |= led_config->led_states[led];
else if (led_config->num_led_states)
val |=
led_config->led_states[led_config->num_led_states - 1];

ret = au8522_writereg(state, 0x8000 |
(led_config->gpio_leds & ~0xc000), val);
if (ret < 0)
return ret;

state->led_state = led;

if (led == 0)
au8522_led_gpio_enable(state, 0);
}

return 0;
}
EXPORT_SYMBOL(au8522_led_ctrl);

int au8522_init(struct dvb_frontend *fe)
{
struct au8522_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);

state->operational_mode = AU8522_DIGITAL_MODE;

/* Clear out any state associated with the digital side of the
chip, so that when it gets powered back up it won't think
that it is already tuned */
state->current_frequency = 0;

au8522_writereg(state, 0xa4, 1 << 5);

au8522_i2c_gate_ctrl(fe, 1);

return 0;
}
EXPORT_SYMBOL(au8522_init);

int au8522_sleep(struct dvb_frontend *fe)
{
struct au8522_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);

/* Only power down if the digital side is currently using the chip */
if (state->operational_mode == AU8522_ANALOG_MODE) {
/* We're not in one of the expected power modes, which means
that the DVB thread is probably telling us to go to sleep
even though the analog frontend has already started using
the chip. So ignore the request */
return 0;
}

/* turn off led */
au8522_led_ctrl(state, 0);

/* Power down the chip */
au8522_writereg(state, 0xa4, 1 << 5);

state->current_frequency = 0;

return 0;
}
EXPORT_SYMBOL(au8522_sleep);
Loading

0 comments on commit 88c43f0

Please sign in to comment.