⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ak470x.c

📁 ak470x的linux驱动程序.ak470x是scart控制芯片.
💻 C
📖 第 1 页 / 共 3 页
字号:
static int ak470x_switch_post_regbackbuffer (struct i2c_client *client){    return ak470x_write_block (client, ak470x_RegBackBuffer, is_ak4702 ? AK4702_NR_REG+1 : AK4706_NR_REG+1);}//  ----------------------- AK470X Mode Function (Loopthrough) -----------------static void ak470x_switch_set_loopthrough (int loopthrough){    // Loopthrough Mode    if (loopthrough)    {    	ak470x_RegBackBuffer[AK470X_CONTROL] |=  0x01;    }    else    {    	ak470x_RegBackBuffer[AK470X_CONTROL] &= ~0x01;    }}//  ----------------------- AK470X Mode Function (Global Switch Setup)  --------int ak470x_switch_set (const av_switch_data* pInfo){    // Store settings    av_current_info = *pInfo;    // Loopthrough Mode    ak470x_switch_set_loopthrough (pInfo->loopthrough);    //    // Reset all register values to zero    //    // - Preserve 'ak470x_RegBackBuffer[AK470X_VOLUME]'    // - Preserve 'ak470x_RegBackBuffer[AK470X_ZEROCROSS]'    //    ak470x_RegBackBuffer[AK470X_START_REG]          =   0x00;    ak470x_RegBackBuffer[AK470X_MAIN_SWITCH]        =   0x04;    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       =   0x00;    ak470x_RegBackBuffer[AK470X_VIDEO_OUTPUT]       =   0x00;    ak470x_RegBackBuffer[AK470X_VIDEO_VOLUME]       =   0x04;    ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   =   0x00;    ak470x_RegBackBuffer[AK470X_BLANKING_MONITOR]   =   0x00;    ak470x_RegBackBuffer[AK4706_MONITOR_MASK]       =   0x08;    ak470x_RegBackBuffer[AK4706_HD_SWITCH]          =   0x00;    ak470x_RegBackBuffer[AK4706_HD_FILTER]          =   0x2A;    // TV Output Source Select    switch(pInfo->attribute[TV_OUTPUT].src_select)    {        case(SRC_PRIMARY) :            switch(pInfo->attribute[TV_OUTPUT].display_mode)            {                case(MODE_RGB) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x01;                    ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0x01;                    break;                case(MODE_YC) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x03;                    break;                case(MODE_CVBS) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x01;                    break;            }            break;        case(SRC_SECONDARY) :            switch(pInfo->attribute[TV_OUTPUT].display_mode)            {                case(MODE_RGB) :                    /* Invalid Mode */                    dprintk(1, KERN_INFO "AK470X: SECONDARY output RGB mode not possible - Falling back to CVBS\n");                    /* Fall through! */                case(MODE_CVBS) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x02;                    break;                case(MODE_YC) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x02;                    break;            }            break;        case(SRC_TVIN) :            /* Invalid Mode */            dprintk(1, KERN_INFO "AK470X: TV OUT using TV IN src not possible\n");            return -EINVAL;            break;        case(SRC_VCRIN) :            /* This mode is used during HD output ... do not route audio from VCR IN! */            // ak470x_RegBackBuffer[AK470X_MAIN_SWITCH]            |= 0x01;            ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]           |= 0x04;            break;        case(SRC_MUTE) :            ak470x_RegBackBuffer[AK470X_MAIN_SWITCH]            |= 0x02;            break;    }    // VCR Output Source Select    switch(pInfo->attribute[VCR_OUTPUT].src_select)    {        case(SRC_PRIMARY) :            switch(pInfo->attribute[VCR_OUTPUT].display_mode)            {                case(MODE_RGB) :                    /* Invalid Mode */                    dprintk(1, KERN_INFO "AK470X: VCR RGB mode not possible - Falling back to CVBS\n");                    /* Fall through! */                case(MODE_CVBS) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x08;                    break;                case(MODE_YC) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x08;                    break;            }            break;        case(SRC_SECONDARY) :            /* Mute the audio output - if not using the primary output source */            ak470x_RegBackBuffer[AK470X_MAIN_SWITCH] |= 0x20;            switch(pInfo->attribute[VCR_OUTPUT].display_mode)            {                case(MODE_RGB) :                    /* Invalid Mode */                    dprintk(1, KERN_INFO "AK470X: VCR RGB mode not possible - Falling back to CVBS\n");                    /* Fall through! */                case(MODE_CVBS) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x10;                    break;                case(MODE_YC) :                    ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]       |= 0x10;                    break;            }            break;        case(SRC_TVIN) :            ak470x_RegBackBuffer[AK470X_MAIN_SWITCH]            |= 0x10;            ak470x_RegBackBuffer[AK470X_VIDEO_SWITCH]           |= 0x18;            break;        case(SRC_VCRIN) :            /* Invalid Mode */            dprintk(1, KERN_INFO "AK470X: VCR OUT using VCR IN src not possible\n");            return -EINVAL;            break;        case(SRC_MUTE) :            ak470x_RegBackBuffer[AK470X_MAIN_SWITCH]            |= 0x20;            break;    }    // TV Output Display Mode Select    switch(pInfo->attribute[TV_OUTPUT].display_mode)    {        case(MODE_RGB) :            ak470x_RegBackBuffer[AK470X_VIDEO_OUTPUT]           |= 0x4F;            break;        case(MODE_YC) :            ak470x_RegBackBuffer[AK470X_VIDEO_OUTPUT]           |= 0x03;            break;        case(MODE_CVBS) :            ak470x_RegBackBuffer[AK470X_VIDEO_OUTPUT]           |= 0x01;            break;    }    // VCR Output Display Mode Select    switch(pInfo->attribute[VCR_OUTPUT].display_mode)    {        case(MODE_RGB) :            /* Invalid Mode */            dprintk(1, KERN_INFO "AK470X: VCR RGB mode not possible - Falling back to CVBS\n");            /* Fall through! */        case(MODE_CVBS) :            ak470x_RegBackBuffer[AK470X_VIDEO_OUTPUT]           |= 0x10;            break;        case(MODE_YC) :            ak470x_RegBackBuffer[AK470X_VIDEO_OUTPUT]           |= 0x30;            break;    }    // Loopthrough Mode Fallback    if (pInfo->loopthrough)    {        ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]       |= 0xC0;    }    else    {        // TV Output Slow Blanking Select        switch(pInfo->attribute[TV_OUTPUT].slow_blanking)        {            case(BLANK_SLOW_OFF) :                break;            case(BLANK_SLOW_16_9) :                ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0x04;                break;            case(BLANK_SLOW_4_3) :                ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0x0C;                break;            case(BLANK_SLOW_FOLLOW) :                ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0xC0;                break;            case(BLANK_SLOW_MONITOR) :                dprintk(1, KERN_INFO "AK470X: MONITOR of TV slow blanking not possible\n");                return -EINVAL;                break;        }        // VCR Output Slow Blanking Select        switch(pInfo->attribute[VCR_OUTPUT].slow_blanking)        {            case(BLANK_SLOW_OFF) :                break;            case(BLANK_SLOW_16_9) :                ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0x10;                break;            case(BLANK_SLOW_4_3) :                ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0x30;                break;            case(BLANK_SLOW_FOLLOW) :                dprintk(1, KERN_INFO "AK470X: FOLLOW for VCR slow blanking not possible\n");                return -EINVAL;                break;            case(BLANK_SLOW_MONITOR) :                ak470x_RegBackBuffer[AK470X_BLANKING_CONTROL]   |= 0x80;                break;        }    }    return ak470x_switch_post_regbackbuffer (ak470x_client);}//  ----------------------- AK470X Mode Get Function (Global Switch Read)  ----int ak470x_switch_get (av_switch_data* pInfo){    *pInfo = av_current_info;    return 0;}//  ----------------------- AK470X function to determine if it is supported on this board or not.  ----int ak470x_switch_installed (){    return ak470x_installed;}//  ----------------------- AK470X Mode Function (Global init)  ----------------static int ak470x_switch_init (struct i2c_client *client){    int i;    for(i=0; i<AK4702_NR_REG+1; i++)    ak470x_RegBackBuffer[i] = 0;    // Default volume : 0dB    ak470x_RegBackBuffer[AK470X_CONTROL]            =   0x70;    ak470x_RegBackBuffer[AK470X_VOLUME]             =   0x1F;    ak470x_RegBackBuffer[AK470X_ZEROCROSS]          =   0x27;    // Initialise the AV switch loop through mode    av_def_info.loopthrough = loopthrough;    return ak470x_switch_set (&av_def_info);}//  ****************************************************************************//  *                                                                          *//  *                           A U D I O     S E C T I O N                    *//  *                                                                          *//  ****************************************************************************////  ----------------------------------------------------------------------------//                          Misc Utilities//  ----------------------------------------------------------------------------//  ----------------------- Channel Number policy   ----------------------------static inline int   ak470x_audio_channel_number_isvalid  (int channel){    return ((channel >= AK470X_AUDIO_CHANNEL_NUMBER_MIN) && (channel <= AK470X_AUDIO_CHANNEL_NUMBER_MAX));}//  ----------------------- Channel Number to index   --------------------------static inline int   ak470x_audio_channel_number_to_index (int channel){    return (channel - AK470X_AUDIO_CHANNEL_NUMBER_MIN);}//  ----------------------------------------------------------------------------//                          Volume norm conversion support//  ----------------------------------------------------------------------------//  ----------------------- AK470X associative volume buffer -------------------static AK470X_AUDIO_IOCTL_VOLUME_t	ak470x_delta_volume [AK470X_AUDIO_CHANNEL_COUNT] = {	[0 ... (AK470X_AUDIO_CHANNEL_COUNT-1)]=	{		.audio_channel 	= 0	,	.master_left 	= AK470X_AUDIO_INTERNAL_GAIN_MIN	,	.master_right	= AK470X_AUDIO_INTERNAL_GAIN_MIN	,	.external_left	= AK470X_AUDIO_EXTERNAL_VOLUME_MIN	,	.external_right = AK470X_AUDIO_EXTERNAL_VOLUME_MIN	}};//  ----------------------- AK470X enforce strict boundaries policy ------------static inline int   ak470x_enforce_volume_boundaries (int val, int min_val, int max_val){    return (val < min_val)? min_val : (val > max_val)? max_val : val;}//  ----------------------- AK470X internal gain to volume conversion   --------static inline int   ak470x_standard_volume (AK470X_AUDIO_MASTER_VOLUME_t Gain){    int gain   =  ak470x_enforce_volume_boundaries ((int)Gain, AK470X_gain_min, AK470X_gain_max);   	return   AK470X_vol_min + (((gain-AK470X_gain_min) * AK470X_vol_mag) / AK470X_gain_mag);}//  ----------------------- AK470X volume to internal gain conversion   --------static inline AK470X_AUDIO_MASTER_VOLUME_t  ak470x_internal_gain (int Volume){    int volume =   ak470x_enforce_volume_boundaries ((int)Volume, AK470X_vol_min, AK470X_vol_max);    return  (AK470X_AUDIO_MASTER_VOLUME_t)     		 AK470X_gain_min + (((volume-AK470X_vol_min) * AK470X_gain_mag) / AK470X_vol_mag);}//  ----------------------------------------------------------------------------//                          I2C Audio I/O support//  ----------------------------------------------------------------------------//  ----------------------- I2C Audio Support Function  (Read )     ------------static inline int ak470x_audio_read  (struct i2c_client *client, u8 addr, u8 *byte_ptr){    return ak470x_audio_block_read  (client, addr, byte_ptr, 1);}//  ----------------------- I2C Audio Support Function  (Write )    ------------static inline int ak470x_audio_write (struct i2c_client *client, u8 addr, u8 *byte_ptr){    return ak470x_audio_block_write (client, addr, byte_ptr, 1);}//  ----------------------------------------------------------------------------//                          Mode control functions//  ----------------------------------------------------------------------------//  ----------------------- AK470X Audio Function (Mode)    --------------------static int ak470x_set_audio_mode(struct i2c_client *client, AK470X_AUDIO_IOCTL_MODE_t *mode){    int     retValue    =   -EINVAL;    AK470X_AUDIO_CHANNEL_NUMBER_t       channel     =   mode->audio_channel;    if (ak470x_audio_channel_number_isvalid(channel))    {        retValue    =   -EINVAL;    // NOT IMPLEMENTED YET        if (retValue) {            dprintk(1,  KERN_INFO "ak470x.c: Failed to setup mode for audio channel %d (0x%X) (Unimplemented)\n",            (int) channel, retValue);            return retValue;        }    }    return retValue;}//  ----------------------------------------------------------------------------//                          Volume control functions//  ----------------------------------------------------------------------------//  ----------------------- AK470X Audio Function (Volume get)  ------------static int ak470x_audio_volume_get (struct i2c_client *client, AK470X_AUDIO_IOCTL_VOLUME_t *volume){    AK470X_AUDIO_CHANNEL_NUMBER_t   channel;    int     retValue    =   -EINVAL;    u8      data_byte   =   0;    // Check channel number    channel     =   volume->audio_channel;    if (!ak470x_audio_channel_number_isvalid(channel))  return retValue;    // I2C buffered I/O    retValue = ak470x_audio_read  (client, AK470X_ADDR_VOLUME, &data_byte);    if (retValue) {        dprintk(1,  KERN_INFO "ak470x.c: Failed to get volume for audio channel %d (0x%X)\n", (int) channel, retValue);        return retValue;    }    // Refresh back buffer    ak470x_RegBackBuffer[AK470X_VOLUME] = data_byte;    // GET Audio Master Volume (L/R)    volume->master_left     =   ak470x_RegBackBuffer[AK470X_VOLUME];    volume->master_right    =   ak470x_RegBackBuffer[AK470X_VOLUME];    return retValue;}//  ----------------------- AK470X Audio Function (Volume set)  ------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -