📄 ak470x.c
字号:
/*****************************************************************************//* Copyright (c) 2008 NXP B.V. All rights are reserved. *//* Reproduction in whole or in part is prohibited without the prior *//* written consent of the copyright owner. *//* *//* This software and any compilation or derivative thereof is, and *//* shall remain the proprietary information of NXP and is *//* highly confidential in nature. Any and all use hereof is restricted *//* and is subject to the terms and conditions set forth in the *//* software license agreement concluded with NXP B.V. *//* *//* Under no circumstances is this software or any derivative thereof *//* to be combined with any Open Source Software, exposed to, or in any *//* way licensed under any Open License Terms without the express prior *//* written permission of the copyright owner. *//* *//* For the purpose of the above, the term Open Source Software means *//* any software that is licensed under Open License Terms. Open *//* License Terms means terms in any license that require as a *//* condition of use, modification and/or distribution of a work *//* *//* 1. the making available of source code or other materials *//* preferred for modification, or *//* *//* 2. the granting of permission for creating derivative *//* works, or *//* *//* 3. the reproduction of certain notices or license terms *//* in derivative works or accompanying documentation, or *//* *//* 4. the granting of a royalty-free license to any party *//* under Intellectual Property Rights *//* *//* regarding the work and/or any work that contains, is combined with, *//* requires or otherwise is based on the work. *//* *//* This software is provided for ease of recompilation only. *//* Modification and reverse engineering of this software are strictly *//* prohibited. *//* *//*****************************************************************************//** @file ak470x.c @brief Linux implementation of the AK470X (AV Scart switch) driver. @b Module: AK470X (AV Scart switch) driver.*//*Rev Date Author Comments-------------------------------------------------------------------------------- 1 20060808 griffiths Removed backend class, modified defaults for STB225 & IFA demo 3 20061115 neill Changes for audio implementation 4 20061127 neill Create as a miscellaneous device 5 20070112 steel update for linux_VARIANT support 6 20071002 neill Add support for YC output 7 20080205 scully Fix popping on boot.6.1.1 20080206 batelaan Update file copyright/license text 8 20080207 scully Merge. 9 20080930 sjones Add power management 10 20080930 sjones Replace magic numbers with macros. Save status register state on suspend.-------------------------------------------------------------------------------- For consistency and standardisation retain the Section Separators.*/#define __AK470X_C__#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/kmod.h>#include <linux/miscdevice.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>// ----------------------- AK470X MODULE Local Headers --------------------#include "ak470x.h"//BPG removed analog backend class//#include "analog_backend.h"// ----------------------- AK470X MODULE Generic Decriptions ----------------#define THIS_MODULE_DESCRIPTION AK470X_MODULE_DESCRIPTIONMODULE_DESCRIPTION(THIS_MODULE_DESCRIPTION);MODULE_AUTHOR("Mike Neill - Alain Clement");MODULE_LICENSE("Proprietary");// ----------------------- AK470X MODULE Debug Level ------------------------static int debug = 0;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Debug level (0-1)");// ----------------------- AK470X MODULE Loopthrough ------------------------static int loopthrough = 0;module_param(loopthrough, int, 0);MODULE_PARM_DESC(loopthrough, "Loopthrough off(0) or On (1)");// ----------------------- AK470X Kernel Debug --------------------------------#ifdef __AK470X_C__#undef dprintk#define dprintk(num, format, args...) \ do { \ if (debug >= num) printk(format, ##args); \ } while (0)#endif//------------------------------------------------------------------------------// FORWARD FUNCTIONS DECLARATION//------------------------------------------------------------------------------// ----------------------- AK470X MODULE Forward Functions Declarations ----static int ak470x_attach_adapter (struct i2c_adapter *adapter );static int ak470x_detach_client (struct i2c_client *client );static int ak470x_command (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg );#ifdef CONFIG_PMstatic int ak470x_suspend(struct i2c_client *client, pm_message_t mesg);static int ak470x_resume(struct i2c_client *client);#endif// ****************************************************************************// * *// * M O D U L E S T R U C T U R E S *// * *// ****************************************************************************// ----------------------- AK470X MODULE Generic Structure ----------------static struct file_operations ak470x_fops = { .ioctl = ak470x_command,};static struct miscdevice ak470x_device = { .minor = MISC_DYNAMIC_MINOR, .name = "ak470x", .fops = &ak470x_fops};// ****************************************************************************// * *// * I 2 C S T R U C T U R E S *// * *// ****************************************************************************#define I2C_AK470X 0x22#define I2C_NAME(s) (s)->name// -----------------------------------------------------------------------------// I2C Support Structures// -----------------------------------------------------------------------------// Generic i2c probe ... addresses: i2c wants 7 bit (without the r/w bit), so '>>1'static unsigned short normal_i2c [ ] = { I2C_AK470X >> 1,I2C_CLIENT_END};static unsigned short probe [2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short ignore [2] = { I2C_CLIENT_END, I2C_CLIENT_END };static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = probe, .ignore = ignore,};static int is_ak4702 = 0;static struct i2c_client *ak470x_client = NULL;static struct i2c_driver i2c_driver_ak470x = { .driver = { .name = "ak470x", }, .id = I2C_DRIVERID_AK470X, .attach_adapter = ak470x_attach_adapter, .detach_client = ak470x_detach_client,#ifdef CONFIG_PM .suspend = ak470x_suspend, .resume = ak470x_resume,#endif};// ****************************************************************************// * *// * S W I T C H S T R U C T U R E S *// * *// ****************************************************************************// ----------------------- AK470X AV Switch Registers Address Mapping --------typedef enum AK470X_SWITCH_REGISTER { AK470X_ADDR_CONTROL = 0 , AK470X_ADDR_MAIN_SWITCH = 1 , AK470X_ADDR_VOLUME = 2 , AK470X_ADDR_ZEROCROSS = 3 , AK470X_ADDR_VIDEO_SWITCH = 4 , AK470X_ADDR_VIDEO_OUTPUT = 5 , AK470X_ADDR_VIDEO_VOLUME = 6 , AK470X_ADDR_BLANKING_CONTROL = 7 , AK470X_ADDR_BLANKING_MONITOR = 8 , AK4706_ADDR_MONITOR_MASK = 9 , AK4706_ADDR_HD_SWITCH = 10 , AK4706_ADDR_HD_FILTER = 11} AK470X_SWITCH_REGISTER_t;// ----------------------- AK470X AV Switch reg. Indexing --------------------typedef enum AK470X_SWITCH_INDEX_t { AK470X_START_REG = 0 , AK470X_CONTROL = 1 , AK470X_MAIN_SWITCH = 2 , AK470X_VOLUME = 3 , AK470X_ZEROCROSS = 4 , AK470X_VIDEO_SWITCH = 5 , AK470X_VIDEO_OUTPUT = 6 , AK470X_VIDEO_VOLUME = 7 , AK470X_BLANKING_CONTROL = 8 , AK470X_BLANKING_MONITOR = 9 , AK4702_NR_REG = 9 , AK4706_MONITOR_MASK = 10 , AK4706_HD_SWITCH = 11 , AK4706_HD_FILTER = 12 , AK4706_NR_REG = 12} AK470X_SWITCH_INDEX_t;#ifdef CONFIG_PM#define AK470X_POWER_DOWN 0x7bstatic int keep_control_status = 0;#endif// ----------------------------------------------------------------------------// AK470X AV Switch Local Data// ----------------------------------------------------------------------------// ----------------------- AK470X AV Switch Data Default: loop through ----static av_switch_data av_def_info ={ 0, { { SRC_PRIMARY, MODE_YC, BLANK_SLOW_OFF}, { SRC_PRIMARY, MODE_CVBS, BLANK_SLOW_OFF} }};// ----------------------- AK470X AV Switch Back Buffer --------------------u8 ak470x_RegBackBuffer[AK4706_NR_REG+1];// ----------------------- AK470X AV Switch - Current Settings ------------static av_switch_data av_current_info;/** * @brief Is the scart switch installed and supported on this board? */static int ak470x_installed = 1;static int ak470x_initialised = 0;// ****************************************************************************// * *// * I 2 C S E C T I O N *// * *// ****************************************************************************// -----------------------------------------------------------------------------// I2C Support Functions// -----------------------------------------------------------------------------// ----------------------- I2C Video Support Function (Write) ------------static int ak470x_write_block ( struct i2c_client* client, const u8* data, unsigned int len){ int ret = -1; u8 reg = *data; /* first register to write to */ /* Sanity check */ if (reg + (len - 1) > AK4706_NR_REG) { return ret; } if (client == NULL) { return 0; } /* the ak470x has an autoincrement function, use it if * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { struct i2c_msg msg; msg.len = len; msg.buf = (char *) data; msg.addr = client->addr; msg.flags = 0; ret = i2c_transfer(client->adapter, &msg, 1); } else { for (++data, --len; len; len--) { if ((ret = i2c_smbus_write_byte_data(client, reg++, *data++)) < 0) { break; } } } return ret;}// ----------------------- I2C Video Support Function (Read ) ------------static inline int ak470x_read (struct i2c_client *client, u8 addr){ if (client == NULL) { return 0; } return i2c_smbus_read_byte_data(client, addr);}// ----------------------- I2C Video Support Function (Write ) ------------static inline int ak470x_write (struct i2c_client *client, u8 addr, u8 byte){ u8 data[2]; if (client == NULL) { return 0; } data[0] = addr; data[1] = byte; return ak470x_write_block ( client, data,2);}// ----------------------- I2C Audio Support Function (Read ) ------------static int ak470x_audio_block_read ( struct i2c_client *client, u8 addr, // register address offset u8 *data, // data buffer ptr (written to) unsigned int len) // data buffer length (bytes){ int ret = -1; if (client == NULL) { return 0; } dprintk(1, KERN_INFO "ak470x.c: Reading %d bytes from address 0x%0X starting at register %d\n", len, client->addr, addr); while (len--) { *data++ = i2c_smbus_read_byte_data (client, addr++); } ret = 0; return ret;}// ----------------------- I2C Audio Support Function (Write) ------------static int ak470x_audio_block_write ( struct i2c_client *client, u8 addr, // register address offset const u8 *data, // data buffer ptr (read from) unsigned int len) // data buffer length (bytes){ int ret = -1; if (client == NULL) { return 0; } dprintk(1, KERN_INFO "ak470x.c: Writing %d bytes to address 0x%0X starting at register %d\n", len, client->addr, addr); while (len--) { if ( (ret = ak470x_write (client, addr++, *data++) ) < 0) { break; } } return ret;}// ****************************************************************************// * *// * S W I T C H S E C T I O N *// * *// ****************************************************************************// ----------------------------------------------------------------------------// Switch control functions// ----------------------------------------------------------------------------// ----------------------- AK470X Mode Function (Write/Post BackBuffer) -------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -