| /* |
| * drivers/amlogic/media/camera/common/plat_ctrl.c |
| * |
| * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
| * |
| * 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. |
| * |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/delay.h> |
| #include <linux/errno.h> |
| #include <linux/fs.h> |
| #include <linux/kernel.h> |
| #include <linux/wait.h> |
| #include <linux/slab.h> |
| #include <linux/mm.h> |
| #include <linux/ioport.h> |
| #include <linux/init.h> |
| #include <linux/sched.h> |
| #include <linux/pci.h> |
| #include <linux/random.h> |
| #include <linux/version.h> |
| #include <linux/mutex.h> |
| #include <linux/videodev2.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/interrupt.h> |
| #include <linux/kthread.h> |
| #include <linux/highmem.h> |
| #include <linux/freezer.h> |
| #include <media/videobuf-vmalloc.h> |
| |
| #include <linux/i2c.h> |
| #include "plat_ctrl.h" |
| |
| /**************************************************************** |
| * i2c functions |
| * **************************************************************/ |
| static int camera_read_buff(struct i2c_client *client, char *buf, int addr_len, |
| int data_len) |
| { |
| int i2c_flag = -1; |
| struct i2c_msg msgs[] = {{ |
| .addr = client->addr, .flags = 0, |
| .len = addr_len, .buf = buf, |
| }, { |
| .addr = client->addr, .flags = I2C_M_RD, |
| .len = data_len, .buf = buf, |
| } |
| }; |
| |
| i2c_flag = i2c_transfer(client->adapter, msgs, 2); |
| |
| return i2c_flag; |
| } |
| |
| static int camera_write_buff(struct i2c_client *client, char *buf, int len) |
| { |
| struct i2c_msg msg[] = {{ |
| .addr = client->addr, .flags = 0, /* |I2C_M_TEN, */ |
| .len = len, .buf = buf, |
| } |
| |
| }; |
| |
| if (i2c_transfer(client->adapter, msg, 1) < 0) { |
| pr_err("i2c error\n"); |
| return -1; |
| } else |
| return 0; |
| } |
| |
| int i2c_get_byte(struct i2c_client *client, unsigned short addr) |
| { |
| unsigned char buff[4]; |
| |
| buff[0] = (unsigned char)((addr >> 8) & 0xff); |
| buff[1] = (unsigned char)(addr & 0xff); |
| |
| if (camera_read_buff(client, buff, 2, 1) < 0) |
| return -1; |
| return buff[0]; |
| } |
| |
| int i2c_get_byte_add8(struct i2c_client *client, unsigned char addr) |
| { |
| unsigned char buff[4]; |
| |
| buff[0] = (unsigned char)(addr & 0xff); |
| |
| if (camera_read_buff(client, buff, 1, 1) < 0) |
| return -1; |
| return buff[0]; |
| } |
| |
| int i2c_get_word(struct i2c_client *client, unsigned short addr) |
| { |
| unsigned short data; |
| unsigned char buff[4]; |
| |
| buff[0] = (unsigned char)((addr >> 8) & 0xff); |
| buff[1] = (unsigned char)(addr & 0xff); |
| |
| if (camera_read_buff(client, buff, 2, 2) < 0) |
| return -1; |
| |
| data = buff[0]; |
| data = (data << 8) | buff[1]; |
| return data; |
| } |
| |
| int i2c_put_byte(struct i2c_client *client, unsigned short addr, |
| unsigned char data) |
| { |
| unsigned char buff[4]; |
| |
| buff[0] = (unsigned char)((addr >> 8) & 0xff); |
| buff[1] = (unsigned char)(addr & 0xff); |
| buff[2] = data; |
| if (camera_write_buff(client, buff, 3) < 0) |
| return -1; |
| return 0; |
| } |
| |
| int i2c_put_word(struct i2c_client *client, unsigned short addr, |
| unsigned short data) |
| { |
| unsigned char buff[4]; |
| |
| buff[0] = (unsigned char)((addr >> 8) & 0xff); |
| buff[1] = (unsigned char)(addr & 0xff); |
| buff[2] = (unsigned char)((data >> 8) & 0xff); |
| buff[3] = (unsigned char)(data & 0xff); |
| |
| if (camera_write_buff(client, buff, 4) < 0) |
| return -1; |
| return 0; |
| } |
| |
| int i2c_put_byte_add8_new(struct i2c_client *client, unsigned char addr, |
| unsigned char data) |
| { |
| unsigned char buff[4]; |
| |
| buff[0] = (unsigned char)(addr & 0xff); |
| buff[1] = (unsigned char)(data & 0xff); |
| if (camera_write_buff(client, buff, 2) < 0) |
| return -1; |
| return 0; |
| } |
| |
| int i2c_put_byte_add8(struct i2c_client *client, char *buf, int len) |
| { |
| if (camera_write_buff(client, buf, len) < 0) |
| return -1; |
| return 0; |
| } |
| |
| int cam_i2c_send_msg(struct i2c_client *client, struct cam_i2c_msg_s i2c_msg) |
| { |
| unsigned char buff[4]; |
| |
| switch (i2c_msg.type) { |
| case ADDR16_DATA16: |
| buff[0] = (unsigned char)((i2c_msg.addr >> 8) & 0xff); |
| buff[1] = (unsigned char)(i2c_msg.addr & 0xff); |
| buff[2] = (unsigned char)((i2c_msg.data >> 8) & 0xff); |
| buff[3] = (unsigned char)(i2c_msg.data & 0xff); |
| if (camera_write_buff(client, buff, 4) < 0) |
| return -1; |
| break; |
| case ADDR16_DATA8: |
| buff[0] = (unsigned char)((i2c_msg.addr >> 8) & 0xff); |
| buff[1] = (unsigned char)(i2c_msg.addr & 0xff); |
| buff[2] = (unsigned char)(i2c_msg.data & 0xff); |
| if (camera_write_buff(client, buff, 3) < 0) |
| return -1; |
| break; |
| case ADDR8_DATA16: |
| buff[0] = (unsigned char)(i2c_msg.addr & 0xff); |
| buff[1] = (unsigned char)((i2c_msg.data >> 8) & 0xff); |
| buff[2] = (unsigned char)(i2c_msg.data & 0xff); |
| if (camera_write_buff(client, buff, 3) < 0) |
| return -1; |
| break; |
| case ADDR8_DATA8: |
| buff[0] = (unsigned char)(i2c_msg.addr & 0xff); |
| buff[1] = (unsigned char)(i2c_msg.data & 0xff); |
| if (camera_write_buff(client, buff, 2) < 0) |
| return -1; |
| break; |
| case TIME_DELAY: |
| msleep(i2c_msg.data); |
| break; |
| default: |
| break; |
| } |
| return 0; |
| } |
| |