2019-05-27 08:55:06 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-11-13 16:07:56 -08:00
/* cx25840 audio functions
*/
# include <linux/videodev2.h>
# include <linux/i2c.h>
# include <media/v4l2-common.h>
2015-11-13 19:40:07 -02:00
# include <media/drv-intf/cx25840.h>
2005-11-13 16:07:56 -08:00
2006-03-25 10:26:09 -03:00
# include "cx25840-core.h"
2005-11-13 16:07:56 -08:00
2009-09-26 23:54:20 -03:00
/*
* Note : The PLL and SRC parameters are based on a reference frequency that
* would ideally be :
*
* NTSC Color subcarrier freq * 8 = 4.5 MHz / 286 * 455 / 2 * 8 = 28.63636363 . . . MHz
*
* However , it ' s not the exact reference frequency that matters , only that the
* firmware and modules that comprise the driver for a particular board all
* use the same value ( close to the ideal value ) .
*
* Comments below will note which reference frequency is assumed for various
* parameters . They will usually be one of
*
* ref_freq = 28.636360 MHz
* or
* ref_freq = 28.636363 MHz
*/
static int cx25840_set_audclk_freq ( struct i2c_client * client , u32 freq )
2005-11-13 16:07:56 -08:00
{
2008-11-29 12:50:06 -03:00
struct cx25840_state * state = to_state ( i2c_get_clientdata ( client ) ) ;
2005-11-13 16:07:56 -08:00
2006-01-09 15:25:42 -02:00
if ( state - > aud_input ! = CX25840_AUDIO_SERIAL ) {
2005-11-13 16:07:56 -08:00
switch ( freq ) {
2006-01-09 15:25:41 -02:00
case 32000 :
2009-09-26 23:54:20 -03:00
/*
* VID_PLL Integer = 0x0f , VID_PLL Post Divider = 0x04
* AUX_PLL Integer = 0x06 , AUX PLL Post Divider = 0x10
*/
cx25840_write4 ( client , 0x108 , 0x1006040f ) ;
/*
* VID_PLL Fraction ( register 0x10c ) = 0x2be2fe
* 28636360 * 0xf .15f 17f 0 / 4 = 108 MHz
* 432 MHz pre - postdivide
*/
/*
* AUX_PLL Fraction = 0x1bb39ee
* 28636363 * 0x6 . dd9cf70 / 0x10 = 32000 * 384
* 196.6 MHz pre - postdivide
* FIXME < 200 MHz is out of specified valid range
* FIXME 28636363 ref_freq doesn ' t match VID PLL ref
*/
cx25840_write4 ( client , 0x110 , 0x01bb39ee ) ;
/*
* SA_MCLK_SEL = 1
* SA_MCLK_DIV = 0x10 = 384 / 384 * AUX_PLL post dvivider
*/
cx25840_write ( client , 0x127 , 0x50 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( is_cx2583x ( state ) )
2006-04-22 10:22:46 -03:00
break ;
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x900 , 0x0801f77f ) ;
cx25840_write4 ( client , 0x904 , 0x0801f77f ) ;
cx25840_write4 ( client , 0x90c , 0x0801f77f ) ;
2005-11-13 16:07:56 -08:00
break ;
2006-01-09 15:25:41 -02:00
case 44100 :
2009-09-26 23:54:20 -03:00
/*
* VID_PLL Integer = 0x0f , VID_PLL Post Divider = 0x04
* AUX_PLL Integer = 0x09 , AUX PLL Post Divider = 0x10
*/
cx25840_write4 ( client , 0x108 , 0x1009040f ) ;
/*
* VID_PLL Fraction ( register 0x10c ) = 0x2be2fe
* 28636360 * 0xf .15f 17f 0 / 4 = 108 MHz
* 432 MHz pre - postdivide
*/
/*
* AUX_PLL Fraction = 0x0ec6bd6
* 28636363 * 0x9 .7635 eb0 / 0x10 = 44100 * 384
* 271 MHz pre - postdivide
* FIXME 28636363 ref_freq doesn ' t match VID PLL ref
*/
cx25840_write4 ( client , 0x110 , 0x00ec6bd6 ) ;
/*
* SA_MCLK_SEL = 1
* SA_MCLK_DIV = 0x10 = 384 / 384 * AUX_PLL post dvivider
*/
cx25840_write ( client , 0x127 , 0x50 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( is_cx2583x ( state ) )
2006-04-22 10:22:46 -03:00
break ;
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x900 , 0x08016d59 ) ;
cx25840_write4 ( client , 0x904 , 0x08016d59 ) ;
cx25840_write4 ( client , 0x90c , 0x08016d59 ) ;
2005-11-13 16:07:56 -08:00
break ;
2006-01-09 15:25:41 -02:00
case 48000 :
2009-09-26 23:54:20 -03:00
/*
* VID_PLL Integer = 0x0f , VID_PLL Post Divider = 0x04
* AUX_PLL Integer = 0x0a , AUX PLL Post Divider = 0x10
*/
cx25840_write4 ( client , 0x108 , 0x100a040f ) ;
/*
* VID_PLL Fraction ( register 0x10c ) = 0x2be2fe
* 28636360 * 0xf .15f 17f 0 / 4 = 108 MHz
* 432 MHz pre - postdivide
*/
/*
* AUX_PLL Fraction = 0x098d6e5
* 28636363 * 0xa .4 c6b728 / 0x10 = 48000 * 384
* 295 MHz pre - postdivide
* FIXME 28636363 ref_freq doesn ' t match VID PLL ref
*/
cx25840_write4 ( client , 0x110 , 0x0098d6e5 ) ;
/*
* SA_MCLK_SEL = 1
* SA_MCLK_DIV = 0x10 = 384 / 384 * AUX_PLL post dvivider
*/
cx25840_write ( client , 0x127 , 0x50 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( is_cx2583x ( state ) )
2006-04-22 10:22:46 -03:00
break ;
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x900 , 0x08014faa ) ;
cx25840_write4 ( client , 0x904 , 0x08014faa ) ;
cx25840_write4 ( client , 0x90c , 0x08014faa ) ;
2005-11-13 16:07:56 -08:00
break ;
}
2006-01-09 15:25:42 -02:00
} else {
2005-11-13 16:07:56 -08:00
switch ( freq ) {
2006-01-09 15:25:41 -02:00
case 32000 :
2009-09-26 23:54:20 -03:00
/*
* VID_PLL Integer = 0x0f , VID_PLL Post Divider = 0x04
* AUX_PLL Integer = 0x08 , AUX PLL Post Divider = 0x1e
*/
cx25840_write4 ( client , 0x108 , 0x1e08040f ) ;
/*
* VID_PLL Fraction ( register 0x10c ) = 0x2be2fe
* 28636360 * 0xf .15f 17f 0 / 4 = 108 MHz
* 432 MHz pre - postdivide
*/
/*
* AUX_PLL Fraction = 0x12a0869
* 28636363 * 0x8 .9504348 / 0x1e = 32000 * 256
* 246 MHz pre - postdivide
* FIXME 28636363 ref_freq doesn ' t match VID PLL ref
*/
cx25840_write4 ( client , 0x110 , 0x012a0869 ) ;
/*
* SA_MCLK_SEL = 1
* SA_MCLK_DIV = 0x14 = 256 / 384 * AUX_PLL post dvivider
*/
cx25840_write ( client , 0x127 , 0x54 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( is_cx2583x ( state ) )
2006-04-22 10:22:46 -03:00
break ;
2009-09-26 23:54:20 -03:00
/* src1_ctl */
/* 0x1.0000 = 32000/32000 */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x8f8 , 0x08010000 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x2.0000 = 2 * (32000/32000) */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x900 , 0x08020000 ) ;
cx25840_write4 ( client , 0x904 , 0x08020000 ) ;
cx25840_write4 ( client , 0x90c , 0x08020000 ) ;
2005-11-13 16:07:56 -08:00
break ;
2006-01-09 15:25:41 -02:00
case 44100 :
2009-09-26 23:54:20 -03:00
/*
* VID_PLL Integer = 0x0f , VID_PLL Post Divider = 0x04
* AUX_PLL Integer = 0x09 , AUX PLL Post Divider = 0x18
*/
cx25840_write4 ( client , 0x108 , 0x1809040f ) ;
/*
* VID_PLL Fraction ( register 0x10c ) = 0x2be2fe
* 28636360 * 0xf .15f 17f 0 / 4 = 108 MHz
* 432 MHz pre - postdivide
*/
/*
* AUX_PLL Fraction = 0x0ec6bd6
* 28636363 * 0x9 .7635 eb0 / 0x18 = 44100 * 256
* 271 MHz pre - postdivide
* FIXME 28636363 ref_freq doesn ' t match VID PLL ref
*/
cx25840_write4 ( client , 0x110 , 0x00ec6bd6 ) ;
/*
* SA_MCLK_SEL = 1
* SA_MCLK_DIV = 0x10 = 256 / 384 * AUX_PLL post dvivider
*/
cx25840_write ( client , 0x127 , 0x50 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( is_cx2583x ( state ) )
2006-04-22 10:22:46 -03:00
break ;
2009-09-26 23:54:20 -03:00
/* src1_ctl */
/* 0x1.60cd = 44100/32000 */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x8f8 , 0x080160cd ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x1.7385 = 2 * (32000/44100) */
2007-12-02 07:03:45 -03:00
cx25840_write4 ( client , 0x900 , 0x08017385 ) ;
cx25840_write4 ( client , 0x904 , 0x08017385 ) ;
cx25840_write4 ( client , 0x90c , 0x08017385 ) ;
2005-11-13 16:07:56 -08:00
break ;
2006-01-09 15:25:41 -02:00
case 48000 :
2009-09-26 23:54:20 -03:00
/*
* VID_PLL Integer = 0x0f , VID_PLL Post Divider = 0x04
* AUX_PLL Integer = 0x0a , AUX PLL Post Divider = 0x18
*/
cx25840_write4 ( client , 0x108 , 0x180a040f ) ;
/*
* VID_PLL Fraction ( register 0x10c ) = 0x2be2fe
* 28636360 * 0xf .15f 17f 0 / 4 = 108 MHz
* 432 MHz pre - postdivide
*/
/*
* AUX_PLL Fraction = 0x098d6e5
* 28636363 * 0xa .4 c6b728 / 0x18 = 48000 * 256
* 295 MHz pre - postdivide
* FIXME 28636363 ref_freq doesn ' t match VID PLL ref
*/
cx25840_write4 ( client , 0x110 , 0x0098d6e5 ) ;
/*
* SA_MCLK_SEL = 1
* SA_MCLK_DIV = 0x10 = 256 / 384 * AUX_PLL post dvivider
*/
cx25840_write ( client , 0x127 , 0x50 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( is_cx2583x ( state ) )
2006-04-22 10:22:46 -03:00
break ;
2009-09-26 23:54:20 -03:00
/* src1_ctl */
/* 0x1.8000 = 48000/32000 */
cx25840_write4 ( client , 0x8f8 , 0x08018000 ) ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x1.5555 = 2 * (32000/48000) */
cx25840_write4 ( client , 0x900 , 0x08015555 ) ;
cx25840_write4 ( client , 0x904 , 0x08015555 ) ;
cx25840_write4 ( client , 0x90c , 0x08015555 ) ;
break ;
}
}
state - > audclk_freq = freq ;
return 0 ;
}
static inline int cx25836_set_audclk_freq ( struct i2c_client * client , u32 freq )
{
return cx25840_set_audclk_freq ( client , freq ) ;
}
static int cx23885_set_audclk_freq ( struct i2c_client * client , u32 freq )
{
struct cx25840_state * state = to_state ( i2c_get_clientdata ( client ) ) ;
if ( state - > aud_input ! = CX25840_AUDIO_SERIAL ) {
switch ( freq ) {
case 32000 :
case 44100 :
case 48000 :
/* We don't have register values
* so avoid destroying registers . */
/* FIXME return -EINVAL; */
break ;
}
} else {
switch ( freq ) {
case 32000 :
case 44100 :
/* We don't have register values
* so avoid destroying registers . */
/* FIXME return -EINVAL; */
break ;
2008-01-10 01:22:39 -03:00
2009-09-26 23:54:20 -03:00
case 48000 :
/* src1_ctl */
/* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
cx25840_write4 ( client , 0x8f8 , 0x0801867c ) ;
2008-01-10 01:22:39 -03:00
2009-09-26 23:54:20 -03:00
/* src3/4/6_ctl */
/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
cx25840_write4 ( client , 0x900 , 0x08014faa ) ;
cx25840_write4 ( client , 0x904 , 0x08014faa ) ;
cx25840_write4 ( client , 0x90c , 0x08014faa ) ;
2005-11-13 16:07:56 -08:00
break ;
}
}
state - > audclk_freq = freq ;
return 0 ;
}
2009-09-26 23:54:20 -03:00
static int cx231xx_set_audclk_freq ( struct i2c_client * client , u32 freq )
{
struct cx25840_state * state = to_state ( i2c_get_clientdata ( client ) ) ;
if ( state - > aud_input ! = CX25840_AUDIO_SERIAL ) {
switch ( freq ) {
case 32000 :
/* src3/4/6_ctl */
/* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
cx25840_write4 ( client , 0x900 , 0x0801f77f ) ;
cx25840_write4 ( client , 0x904 , 0x0801f77f ) ;
cx25840_write4 ( client , 0x90c , 0x0801f77f ) ;
break ;
case 44100 :
/* src3/4/6_ctl */
/* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
cx25840_write4 ( client , 0x900 , 0x08016d59 ) ;
cx25840_write4 ( client , 0x904 , 0x08016d59 ) ;
cx25840_write4 ( client , 0x90c , 0x08016d59 ) ;
break ;
case 48000 :
/* src3/4/6_ctl */
/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
cx25840_write4 ( client , 0x900 , 0x08014faa ) ;
cx25840_write4 ( client , 0x904 , 0x08014faa ) ;
cx25840_write4 ( client , 0x90c , 0x08014faa ) ;
break ;
}
} else {
switch ( freq ) {
/* FIXME These cases make different assumptions about audclk */
case 32000 :
/* src1_ctl */
/* 0x1.0000 = 32000/32000 */
cx25840_write4 ( client , 0x8f8 , 0x08010000 ) ;
/* src3/4/6_ctl */
/* 0x2.0000 = 2 * (32000/32000) */
cx25840_write4 ( client , 0x900 , 0x08020000 ) ;
cx25840_write4 ( client , 0x904 , 0x08020000 ) ;
cx25840_write4 ( client , 0x90c , 0x08020000 ) ;
break ;
case 44100 :
/* src1_ctl */
/* 0x1.60cd = 44100/32000 */
cx25840_write4 ( client , 0x8f8 , 0x080160cd ) ;
/* src3/4/6_ctl */
/* 0x1.7385 = 2 * (32000/44100) */
cx25840_write4 ( client , 0x900 , 0x08017385 ) ;
cx25840_write4 ( client , 0x904 , 0x08017385 ) ;
cx25840_write4 ( client , 0x90c , 0x08017385 ) ;
break ;
case 48000 :
/* src1_ctl */
/* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
cx25840_write4 ( client , 0x8f8 , 0x0801867c ) ;
/* src3/4/6_ctl */
/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
cx25840_write4 ( client , 0x900 , 0x08014faa ) ;
cx25840_write4 ( client , 0x904 , 0x08014faa ) ;
cx25840_write4 ( client , 0x90c , 0x08014faa ) ;
break ;
}
}
state - > audclk_freq = freq ;
return 0 ;
}
static int set_audclk_freq ( struct i2c_client * client , u32 freq )
{
struct cx25840_state * state = to_state ( i2c_get_clientdata ( client ) ) ;
if ( freq ! = 32000 & & freq ! = 44100 & & freq ! = 48000 )
return - EINVAL ;
if ( is_cx231xx ( state ) )
return cx231xx_set_audclk_freq ( client , freq ) ;
if ( is_cx2388x ( state ) )
return cx23885_set_audclk_freq ( client , freq ) ;
if ( is_cx2583x ( state ) )
return cx25836_set_audclk_freq ( client , freq ) ;
return cx25840_set_audclk_freq ( client , freq ) ;
}
2006-01-09 15:25:42 -02:00
void cx25840_audio_set_path ( struct i2c_client * client )
2005-11-13 16:07:56 -08:00
{
2008-11-29 12:50:06 -03:00
struct cx25840_state * state = to_state ( i2c_get_clientdata ( client ) ) ;
2005-11-13 16:07:56 -08:00
2010-07-10 15:02:21 -03:00
if ( ! is_cx2583x ( state ) ) {
/* assert soft reset */
cx25840_and_or ( client , 0x810 , ~ 0x1 , 0x01 ) ;
/* stop microcontroller */
cx25840_and_or ( client , 0x803 , ~ 0x10 , 0 ) ;
/* Mute everything to prevent the PFFT! */
cx25840_write ( client , 0x8d3 , 0x1f ) ;
if ( state - > aud_input = = CX25840_AUDIO_SERIAL ) {
/* Set Path1 to Serial Audio Input */
cx25840_write4 ( client , 0x8d0 , 0x01011012 ) ;
/* The microcontroller should not be started for the
* non - tuner inputs : autodetection is specific for
* TV audio . */
} else {
/* Set Path1 to Analog Demod Main Channel */
cx25840_write4 ( client , 0x8d0 , 0x1f063870 ) ;
}
2006-04-29 12:11:18 -03:00
}
set_audclk_freq ( client , state - > audclk_freq ) ;
2005-11-13 16:07:56 -08:00
2010-07-10 15:02:21 -03:00
if ( ! is_cx2583x ( state ) ) {
if ( state - > aud_input ! = CX25840_AUDIO_SERIAL ) {
/* When the microcontroller detects the
* audio format , it will unmute the lines */
cx25840_and_or ( client , 0x803 , ~ 0x10 , 0x10 ) ;
}
2007-08-07 07:16:07 -03:00
2010-07-10 15:02:21 -03:00
/* deassert soft reset */
cx25840_and_or ( client , 0x810 , ~ 0x1 , 0x00 ) ;
2008-01-10 01:22:39 -03:00
2010-07-10 15:02:21 -03:00
/* Ensure the controller is running when we exit */
if ( is_cx2388x ( state ) | | is_cx231xx ( state ) )
cx25840_and_or ( client , 0x803 , ~ 0x10 , 0x10 ) ;
}
2005-11-13 16:07:56 -08:00
}
2006-01-09 15:32:41 -02:00
static void set_volume ( struct i2c_client * client , int volume )
2005-11-13 16:07:56 -08:00
{
2007-08-05 08:00:36 -03:00
int vol ;
/* Convert the volume to msp3400 values (0-127) */
vol = volume > > 9 ;
2005-11-13 16:07:56 -08:00
/* now scale it up to cx25840 values
* - 114 dB to - 96 dB maps to 0
* this should be 19 , but in my testing that was 4 dB too loud */
if ( vol < = 23 ) {
vol = 0 ;
} else {
vol - = 23 ;
}
/* PATH1_VOLUME */
2012-01-04 10:47:57 -03:00
cx25840_write ( client , 0x8d4 , 228 - ( vol * 2 ) ) ;
2005-11-13 16:07:56 -08:00
}
2006-01-09 15:32:41 -02:00
static void set_balance ( struct i2c_client * client , int balance )
2005-11-13 16:07:56 -08:00
{
int bal = balance > > 8 ;
if ( bal > 0x80 ) {
/* PATH1_BAL_LEFT */
cx25840_and_or ( client , 0x8d5 , 0x7f , 0x80 ) ;
/* PATH1_BAL_LEVEL */
cx25840_and_or ( client , 0x8d5 , ~ 0x7f , bal & 0x7f ) ;
} else {
/* PATH1_BAL_LEFT */
cx25840_and_or ( client , 0x8d5 , 0x7f , 0x00 ) ;
/* PATH1_BAL_LEVEL */
cx25840_and_or ( client , 0x8d5 , ~ 0x7f , 0x80 - bal ) ;
}
}
2009-03-30 06:26:40 -03:00
int cx25840_s_clock_freq ( struct v4l2_subdev * sd , u32 freq )
2005-11-13 16:07:56 -08:00
{
2009-03-30 06:26:40 -03:00
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct cx25840_state * state = to_state ( sd ) ;
2006-04-29 12:11:18 -03:00
int retval ;
2005-11-13 16:07:56 -08:00
2009-09-26 23:47:21 -03:00
if ( ! is_cx2583x ( state ) )
2009-03-30 06:26:40 -03:00
cx25840_and_or ( client , 0x810 , ~ 0x1 , 1 ) ;
if ( state - > aud_input ! = CX25840_AUDIO_SERIAL ) {
cx25840_and_or ( client , 0x803 , ~ 0x10 , 0 ) ;
cx25840_write ( client , 0x8d3 , 0x1f ) ;
}
retval = set_audclk_freq ( client , freq ) ;
if ( state - > aud_input ! = CX25840_AUDIO_SERIAL )
cx25840_and_or ( client , 0x803 , ~ 0x10 , 0x10 ) ;
2009-09-26 23:47:21 -03:00
if ( ! is_cx2583x ( state ) )
2009-03-30 06:26:40 -03:00
cx25840_and_or ( client , 0x810 , ~ 0x1 , 0 ) ;
return retval ;
}
2006-01-09 15:25:42 -02:00
2010-08-06 10:55:39 -03:00
static int cx25840_audio_s_ctrl ( struct v4l2_ctrl * ctrl )
2009-03-30 06:26:40 -03:00
{
2010-08-06 10:55:39 -03:00
struct v4l2_subdev * sd = to_sd ( ctrl ) ;
struct cx25840_state * state = to_state ( sd ) ;
2009-03-30 06:26:40 -03:00
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
2006-01-09 15:25:42 -02:00
2009-03-30 06:26:40 -03:00
switch ( ctrl - > id ) {
case V4L2_CID_AUDIO_VOLUME :
2010-08-06 10:55:39 -03:00
if ( state - > mute - > val )
set_volume ( client , 0 ) ;
else
set_volume ( client , state - > volume - > val ) ;
2009-03-30 06:26:40 -03:00
break ;
case V4L2_CID_AUDIO_BASS :
2010-08-06 10:55:39 -03:00
/* PATH1_EQ_BASS_VOL */
cx25840_and_or ( client , 0x8d9 , ~ 0x3f ,
48 - ( ctrl - > val * 48 / 0xffff ) ) ;
2009-03-30 06:26:40 -03:00
break ;
case V4L2_CID_AUDIO_TREBLE :
2010-08-06 10:55:39 -03:00
/* PATH1_EQ_TREBLE_VOL */
cx25840_and_or ( client , 0x8db , ~ 0x3f ,
48 - ( ctrl - > val * 48 / 0xffff ) ) ;
2009-03-30 06:26:40 -03:00
break ;
case V4L2_CID_AUDIO_BALANCE :
2010-08-06 10:55:39 -03:00
set_balance ( client , ctrl - > val ) ;
2009-03-30 06:26:40 -03:00
break ;
2005-11-13 16:07:56 -08:00
default :
return - EINVAL ;
}
2009-03-30 06:26:40 -03:00
return 0 ;
}
2005-11-13 16:07:56 -08:00
2010-08-06 10:55:39 -03:00
const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = {
. s_ctrl = cx25840_audio_s_ctrl ,
} ;