You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kernel_samsung_sm7125/drivers/video/fbdev/msm/mdss_spi_client.c

219 lines
4.6 KiB

/* Copyright (c) 2017-2018, The Linux Foundation. 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 version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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/kernel.h>
#include <linux/spi/spi.h>
#include "mdss_spi_client.h"
#define MAX_READ_SPEED_HZ 9600000
#define SPI_PANEL_COMMAND_LEN 1
static struct spi_device *mdss_spi_client;
int mdss_spi_read_data(u8 reg_addr, u8 *data, u8 len)
{
int rc = 0;
u32 max_speed_hz;
u8 memory_write_reg = 0x2c;
u8 empty_pack[] = {0x29, 0x29, 0x29};
struct spi_transfer t[4] = {
[0] = {
.tx_buf = &reg_addr,
.len = 1,
},
[1] = {
.rx_buf = data,
.len = len,
},
[2] = {
.tx_buf = &empty_pack,
.len = 3,
},
[3] = {
.tx_buf = &memory_write_reg,
.len = 1,
}
};
struct spi_message m;
if (!mdss_spi_client) {
pr_err("%s: spi client not available\n", __func__);
return -EINVAL;
}
mdss_spi_client->bits_per_word = 8;
max_speed_hz = mdss_spi_client->max_speed_hz;
mdss_spi_client->max_speed_hz = MAX_READ_SPEED_HZ;
spi_message_init(&m);
spi_message_add_tail(&t[0], &m);
spi_message_add_tail(&t[1], &m);
rc = spi_sync(mdss_spi_client, &m);
if (rc) {
pr_err("%s: send panel reg failed\n", __func__);
return rc;
}
spi_message_init(&m);
spi_message_add_tail(&t[2], &m);
rc = spi_sync(mdss_spi_client, &m);
if (rc) {
pr_err("%s: send empty package failed\n", __func__);
return rc;
}
spi_message_init(&m);
spi_message_add_tail(&t[3], &m);
rc = spi_sync(mdss_spi_client, &m);
mdss_spi_client->max_speed_hz = max_speed_hz;
if (rc) {
pr_err("%s: send memory write reg failed\n", __func__);
return rc;
}
return rc;
}
int mdss_spi_tx_command(const void *buf)
{
int rc = 0;
struct spi_transfer t = {
.tx_buf = buf,
.len = SPI_PANEL_COMMAND_LEN,
};
struct spi_message m;
if (!mdss_spi_client) {
pr_err("%s: spi client not available\n", __func__);
return -EINVAL;
}
mdss_spi_client->bits_per_word = 8;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
rc = spi_sync(mdss_spi_client, &m);
if (rc)
pr_err("%s: send panel command failed\n", __func__);
return rc;
}
int mdss_spi_tx_parameter(const void *buf, size_t len)
{
int rc = 0;
struct spi_transfer t = {
.tx_buf = buf,
.len = len,
};
struct spi_message m;
if (!mdss_spi_client) {
pr_err("%s: spi client not available\n", __func__);
return -EINVAL;
}
mdss_spi_client->bits_per_word = 8;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
rc = spi_sync(mdss_spi_client, &m);
if (rc)
pr_err("%s: send panel parameter failed\n", __func__);
return rc;
}
int mdss_spi_tx_pixel(const void *buf, size_t len,
void (*spi_tx_compelet)(void *), void *ctx)
{
int rc = 0;
static struct spi_transfer t;
static struct spi_message m;
if (!mdss_spi_client) {
pr_err("%s: spi client not available\n", __func__);
return -EINVAL;
}
mdss_spi_client->bits_per_word = 16;
t.tx_buf = buf;
t.len = len;
spi_message_init(&m);
m.complete = spi_tx_compelet;
m.context = ctx;
spi_message_add_tail(&t, &m);
rc = spi_async(mdss_spi_client, &m);
if (rc)
pr_err("%s: send FrameBuffer data failed\n", __func__);
return rc;
}
static int mdss_spi_client_probe(struct spi_device *spidev)
{
int irq;
int cs;
int cpha, cpol, cs_high;
u32 max_speed;
irq = spidev->irq;
cs = spidev->chip_select;
cpha = (spidev->mode & SPI_CPHA) ? 1:0;
cpol = (spidev->mode & SPI_CPOL) ? 1:0;
cs_high = (spidev->mode & SPI_CS_HIGH) ? 1:0;
max_speed = spidev->max_speed_hz;
pr_debug("cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x] Max_speed[%d]\n",
cs, cpha, cpol, cs_high, max_speed);
mdss_spi_client = spidev;
return 0;
}
static const struct of_device_id mdss_spi_dt_match[] = {
{ .compatible = "qcom,mdss-spi-client" },
{},
};
static struct spi_driver mdss_spi_client_driver = {
.probe = mdss_spi_client_probe,
.driver = {
.name = "mdss-spi-client",
.owner = THIS_MODULE,
.of_match_table = mdss_spi_dt_match,
},
};
static int __init mdss_spi_init(void)
{
int ret;
ret = spi_register_driver(&mdss_spi_client_driver);
if (ret) {
pr_err("register mdss spi client driver failed!\n");
return ret;
}
return 0;
}
module_init(mdss_spi_init);
static void __exit mdss_spi_exit(void)
{
spi_unregister_driver(&mdss_spi_client_driver);
}
module_exit(mdss_spi_exit);