blob: ea828324e892c34341d1763417a60cdcbebbca92 [file] [log] [blame]
/* Copyright (c) 2012-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/delay.h>
#include "msm_jpeg_hw.h"
#include "msm_jpeg_common.h"
#include "msm_camera_io_util.h"
#include <linux/io.h>
int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
struct msm_jpeg_hw_buf *buf, void *base)
{
int buf_free_index = -1;
if (!pingpong_hw->buf_status[0]) {
buf_free_index = 0;
} else if (!pingpong_hw->buf_status[1]) {
buf_free_index = 1;
} else {
JPEG_PR_ERR("%s:%d: pingpong buffer busy\n",
__func__, __LINE__);
return -EBUSY;
}
pingpong_hw->buf[buf_free_index] = *buf;
pingpong_hw->buf_status[buf_free_index] = 1;
if (pingpong_hw->is_fe) {
/* it is fe */
msm_jpeg_hw_fe_buffer_update(
&pingpong_hw->buf[buf_free_index], buf_free_index,
base);
} else {
/* it is we */
msm_jpeg_hw_we_buffer_update(
&pingpong_hw->buf[buf_free_index], buf_free_index,
base);
}
return 0;
}
int msm_jpegdma_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
struct msm_jpeg_hw_buf *buf, void *base)
{
int buf_free_index = -1;
if (!pingpong_hw->buf_status[0]) {
buf_free_index = 0;
} else if (!pingpong_hw->buf_status[1]) {
buf_free_index = 1;
} else {
JPEG_PR_ERR("%s:%d: pingpong buffer busy\n",
__func__, __LINE__);
return -EBUSY;
}
pingpong_hw->buf[buf_free_index] = *buf;
pingpong_hw->buf_status[buf_free_index] = 1;
if (pingpong_hw->is_fe) {
/* it is fe */
msm_jpegdma_hw_fe_buffer_update(
&pingpong_hw->buf[buf_free_index], buf_free_index,
base);
} else {
/* it is we */
msm_jpegdma_hw_we_buffer_update(
&pingpong_hw->buf[buf_free_index], buf_free_index,
base);
}
return 0;
}
void *msm_jpeg_hw_pingpong_irq(struct msm_jpeg_hw_pingpong *pingpong_hw)
{
struct msm_jpeg_hw_buf *buf_p = NULL;
if (pingpong_hw->buf_status[pingpong_hw->buf_active_index]) {
buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
pingpong_hw->buf_status[pingpong_hw->buf_active_index] = 0;
}
pingpong_hw->buf_active_index = !pingpong_hw->buf_active_index;
return (void *) buf_p;
}
void *msm_jpeg_hw_pingpong_active_buffer(
struct msm_jpeg_hw_pingpong *pingpong_hw)
{
struct msm_jpeg_hw_buf *buf_p = NULL;
if (pingpong_hw->buf_status[pingpong_hw->buf_active_index])
buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
return (void *) buf_p;
}
static struct msm_jpeg_hw_cmd hw_cmd_irq_get_status[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_READ, 1, JPEG_IRQ_STATUS_ADDR,
JPEG_IRQ_STATUS_BMSK, {0} },
};
int msm_jpeg_hw_irq_get_status(void *base)
{
uint32_t n_irq_status = 0;
n_irq_status = msm_jpeg_hw_read(&hw_cmd_irq_get_status[0], base);
return n_irq_status;
}
static struct msm_jpeg_hw_cmd hw_cmd_irq_get_dmastatus[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_READ, 1, JPEGDMA_IRQ_STATUS_ADDR,
JPEGDMA_IRQ_STATUS_BMSK, {0} },
};
int msm_jpegdma_hw_irq_get_status(void *base)
{
uint32_t n_irq_status = 0;
n_irq_status = msm_jpeg_hw_read(&hw_cmd_irq_get_dmastatus[0], base);
return n_irq_status;
}
static struct msm_jpeg_hw_cmd hw_cmd_encode_output_size[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_READ, 1,
JPEG_ENCODE_OUTPUT_SIZE_STATUS_ADDR,
JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK, {0} },
};
long msm_jpeg_hw_encode_output_size(void *base)
{
uint32_t encode_output_size = 0;
encode_output_size = msm_jpeg_hw_read(&hw_cmd_encode_output_size[0],
base);
return encode_output_size;
}
void msm_jpeg_hw_irq_clear(uint32_t mask, uint32_t data, void *base)
{
struct msm_jpeg_hw_cmd cmd_irq_clear;
cmd_irq_clear.type = MSM_JPEG_HW_CMD_TYPE_WRITE;
cmd_irq_clear.n = 1;
cmd_irq_clear.offset = JPEG_IRQ_CLEAR_ADDR;
cmd_irq_clear.mask = mask;
cmd_irq_clear.data = data;
JPEG_DBG("%s:%d] mask %0x data %0x", __func__, __LINE__, mask, data);
msm_jpeg_hw_write(&cmd_irq_clear, base);
}
void msm_jpegdma_hw_irq_clear(uint32_t mask, uint32_t data, void *base)
{
struct msm_jpeg_hw_cmd cmd_irq_clear;
cmd_irq_clear.type = MSM_JPEG_HW_CMD_TYPE_WRITE;
cmd_irq_clear.n = 1;
cmd_irq_clear.offset = JPEGDMA_IRQ_CLEAR_ADDR;
cmd_irq_clear.mask = mask;
cmd_irq_clear.data = data;
JPEG_DBG("%s:%d] mask %0x data %0x", __func__, __LINE__, mask, data);
msm_jpeg_hw_write(&cmd_irq_clear, base);
}
static struct msm_jpeg_hw_cmd hw_cmd_fe_ping_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_CMD_ADDR,
JPEG_CMD_BMSK, {JPEG_CMD_CLEAR_WRITE_PLN_QUEUES} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_RD_OFFSET_ADDR,
JPEG_PLN0_RD_OFFSET_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_RD_PNTR_ADDR,
JPEG_PLN0_RD_PNTR_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_RD_OFFSET_ADDR,
JPEG_PLN1_RD_OFFSET_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_RD_PNTR_ADDR,
JPEG_PLN1_RD_PNTR_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN2_RD_OFFSET_ADDR,
JPEG_PLN1_RD_OFFSET_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN2_RD_PNTR_ADDR,
JPEG_PLN2_RD_PNTR_BMSK, {0} },
};
void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
uint8_t pingpong_index, void *base)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
if (pingpong_index == 0) {
hw_cmd_p = &hw_cmd_fe_ping_update[0];
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->y_buffer_addr;
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->cbcr_buffer_addr;
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->pln2_addr;
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
}
}
static struct msm_jpeg_hw_cmd hw_dma_cmd_fe_ping_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_IRQ_MASK_ADDR,
JPEGDMA_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_CMD_ADDR,
JPEGDMA_CMD_BMSK, {JPEGDMA_CMD_CLEAR_READ_PLN_QUEUES} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_FE_0_RD_PNTR,
JPEG_PLN0_RD_PNTR_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_FE_1_RD_PNTR,
JPEG_PLN1_RD_PNTR_BMSK, {0} },
};
void msm_jpegdma_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
uint8_t pingpong_index, void *base)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
if (pingpong_index != 0)
return;
hw_cmd_p = &hw_dma_cmd_fe_ping_update[0];
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->y_buffer_addr;
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->cbcr_buffer_addr;
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_cmd_fe_start[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_CMD_ADDR,
JPEG_CMD_BMSK, {JPEG_OFFLINE_CMD_START} },
};
void msm_jpeg_hw_fe_start(void *base)
{
msm_jpeg_hw_write(&hw_cmd_fe_start[0], base);
}
static struct msm_jpeg_hw_cmd hw_cmd_we_ping_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_WR_PNTR_ADDR,
JPEG_PLN0_WR_PNTR_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_WR_PNTR_ADDR,
JPEG_PLN0_WR_PNTR_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN2_WR_PNTR_ADDR,
JPEG_PLN0_WR_PNTR_BMSK, {0} },
};
void msm_jpeg_decode_status(void *base)
{
uint32_t data;
data = msm_camera_io_r(
(void __iomem *)(base + JPEG_DECODE_MCUS_DECODED_STATUS));
JPEG_DBG_HIGH("Decode MCUs decode status %u", data);
data = msm_camera_io_r(
(void __iomem *)(base + JPEG_DECODE_BITS_CONSUMED_STATUS));
JPEG_DBG_HIGH("Decode bits consumed status %u", data);
data = msm_camera_io_r(
(void __iomem *)(base + JPEG_DECODE_PRED_Y_STATE));
JPEG_DBG_HIGH("Decode prediction Y state %u", data);
data = msm_camera_io_r(
(void __iomem *)(base + JPEG_DECODE_PRED_C_STATE));
JPEG_DBG_HIGH("Decode prediction C state %u", data);
data = msm_camera_io_r(
(void __iomem *)(base + JPEG_DECODE_RSM_STATE));
JPEG_DBG_HIGH("Decode prediction RSM state %u", data);
}
void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
uint8_t pingpong_index, void *base)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
if (pingpong_index == 0) {
hw_cmd_p = &hw_cmd_we_ping_update[0];
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->y_buffer_addr;
JPEG_DBG_HIGH("%s Output pln0 buffer address is %x\n", __func__,
p_input->y_buffer_addr);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->cbcr_buffer_addr;
JPEG_DBG_HIGH("%s Output pln1 buffer address is %x\n", __func__,
p_input->cbcr_buffer_addr);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->pln2_addr;
JPEG_DBG_HIGH("%s Output pln2 buffer address is %x\n", __func__,
p_input->pln2_addr);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
}
}
static struct msm_jpeg_hw_cmd hw_dma_cmd_we_ping_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_CMD_ADDR,
JPEGDMA_CMD_BMSK, {JPEGDMA_CMD_CLEAR_WRITE_PLN_QUEUES} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_WE_0_WR_PNTR,
JPEG_PLN0_WR_PNTR_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_WE_1_WR_PNTR,
JPEG_PLN0_WR_PNTR_BMSK, {0} },
};
void msm_jpegdma_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
uint8_t pingpong_index, void *base)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
if (pingpong_index != 0)
return;
hw_cmd_p = &hw_dma_cmd_we_ping_update[0];
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->y_buffer_addr;
JPEG_DBG_HIGH("%s Output we 0 buffer address is %x\n", __func__,
p_input->y_buffer_addr);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = p_input->cbcr_buffer_addr;
JPEG_DBG_HIGH("%s Output we 1 buffer address is %x\n", __func__,
p_input->cbcr_buffer_addr);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_cmd_fe_mmu_prefetch[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S0_MMU_PF_ADDR_MIN,
MSM_JPEG_S0_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S0_MMU_PF_ADDR_MAX,
MSM_JPEG_S0_MMU_PF_ADDR_MAX_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S1_MMU_PF_ADDR_MIN,
MSM_JPEG_S1_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S1_MMU_PF_ADDR_MAX,
MSM_JPEG_S1_MMU_PF_ADDR_MAX_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S2_MMU_PF_ADDR_MIN,
MSM_JPEG_S2_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S2_MMU_PF_ADDR_MAX,
MSM_JPEG_S2_MMU_PF_ADDR_MAX_BMSK, {0} },
};
/*
* msm_jpeg_hw_fe_mmu_prefetch() - writes fe min/max addrs for each plane to
* MMU prefetch registers.
* @buf: Pointer to jpeg hw buffer.
* @base: Pointer to base address.
* @decode_flag: Jpeg decode flag.
*
* This function writes fe min/max address for each plane to MMU prefetch
* registers, MMU prefetch hardware will only prefetch address translations
* within this min/max boundary.
*
* Return: None.
*/
void msm_jpeg_hw_fe_mmu_prefetch(struct msm_jpeg_hw_buf *buf, void *base,
uint8_t decode_flag)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
hw_cmd_p = &hw_cmd_fe_mmu_prefetch[0];
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
JPEG_DBG("%s:%d: MIN y_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
if (buf->y_len)
tmp_hw_cmd.data += buf->y_len - 1;
JPEG_DBG("%s:%d: MAX y_buf_addr %08x, y_len %d\n",
__func__, __LINE__, tmp_hw_cmd.data, buf->y_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
if (!decode_flag) {
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->cbcr_buffer_addr;
JPEG_DBG("%s:%d: MIN cbcr_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->cbcr_buffer_addr;
if (buf->cbcr_len)
tmp_hw_cmd.data += buf->cbcr_len - 1;
JPEG_DBG("%s:%d: MAX cbcr_buf_addr %08x, cbcr_len %d\n"
, __func__, __LINE__, tmp_hw_cmd.data, buf->cbcr_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->pln2_addr;
JPEG_DBG("%s:%d: MIN pln2_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->pln2_addr;
if (buf->pln2_len)
tmp_hw_cmd.data += buf->pln2_len - 1;
JPEG_DBG("%s:%d: MAX pln2_buf_addr %08x, pln2_len %d\n"
, __func__, __LINE__, tmp_hw_cmd.data, buf->pln2_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
}
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_cmd_we_mmu_prefetch[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S1_MMU_PF_ADDR_MIN,
MSM_JPEG_S1_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S1_MMU_PF_ADDR_MAX,
MSM_JPEG_S1_MMU_PF_ADDR_MAX_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S2_MMU_PF_ADDR_MIN,
MSM_JPEG_S2_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S2_MMU_PF_ADDR_MAX,
MSM_JPEG_S2_MMU_PF_ADDR_MAX_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S3_MMU_PF_ADDR_MIN,
MSM_JPEG_S3_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEG_S3_MMU_PF_ADDR_MAX,
MSM_JPEG_S3_MMU_PF_ADDR_MAX_BMSK, {0} },
};
/*
* msm_jpeg_hw_we_mmu_prefetch() - write we min/max addrs for each plane to
* MMU prefetch registers.
* @buf: Pointer to jpeg hw buffer.
* @base: Pointer to base address.
* @decode_flag: Jpeg decode flag.
*
* This function writes we min/max address for each plane to MMU prefetch
* registers, MMU prefetch hardware will only prefetch address translations
* within this min/max boundary.
*
* Return: None.
*/
void msm_jpeg_hw_we_mmu_prefetch(struct msm_jpeg_hw_buf *buf, void *base,
uint8_t decode_flag)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
hw_cmd_p = &hw_cmd_we_mmu_prefetch[0];
/* ensure write is done */
wmb();
if (decode_flag) {
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
JPEG_DBG("%s:%d: MIN y_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
if (buf->y_len)
tmp_hw_cmd.data += buf->y_len - 1;
JPEG_DBG("%s:%d: MAX y_buf_addr %08x, y_len %d\n",
__func__, __LINE__, tmp_hw_cmd.data, buf->y_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->cbcr_buffer_addr;
JPEG_DBG("%s:%d: MIN cbcr_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->cbcr_buffer_addr;
if (buf->cbcr_len)
tmp_hw_cmd.data += buf->cbcr_len - 1;
JPEG_DBG("%s:%d: MAX cbcr_buf_addr %08x, cbcr_len %d\n"
, __func__, __LINE__, tmp_hw_cmd.data, buf->cbcr_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->pln2_addr;
JPEG_DBG("%s:%d: MIN pln2_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->pln2_addr;
if (buf->pln2_len)
tmp_hw_cmd.data += buf->pln2_len - 1;
JPEG_DBG("%s:%d: MIN pln2_buf_addr %08x, pln2_len %d\n"
, __func__, __LINE__, tmp_hw_cmd.data, buf->pln2_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
} else {
hw_cmd_p += 4;
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
JPEG_DBG("%s:%d: MIN y_buf_addr %08x\n",
__func__, __LINE__, tmp_hw_cmd.data);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
if (buf->y_len)
tmp_hw_cmd.data += buf->y_len - 1;
JPEG_DBG("%s:%d: MAX y_buf_addr %08x, y_len %d\n",
__func__, __LINE__, tmp_hw_cmd.data, buf->y_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
}
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_dma_cmd_fe_mmu_prefetch[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_S0_MMU_PF_ADDR_MIN,
MSM_JPEGDMA_S0_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_S0_MMU_PF_ADDR_MAX,
MSM_JPEGDMA_S0_MMU_PF_ADDR_MAX_BMSK, {0} },
};
/*
* msm_jpegdma_hw_fe_mmu_prefetch() - write DMA fe min/max addrs to
* MMU prefetch registers.
* @buf: Pointer to jpeg hw buffer.
* @base: Pointer to base address.
*
* This function writes DMA fe min/max address for each plane to MMU prefetch
* registers, MMU prefetch hardware will only prefetch address translations
* with in this min/max boundary.
*
* Return: None.
*/
void msm_jpegdma_hw_fe_mmu_prefetch(struct msm_jpeg_hw_buf *buf, void *base)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
hw_cmd_p = &hw_dma_cmd_fe_mmu_prefetch[0];
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
JPEG_DBG("%s:%d: MIN DMA addr %08x , reg offset %08x\n",
__func__, __LINE__, tmp_hw_cmd.data, tmp_hw_cmd.offset);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
if (buf->y_len)
tmp_hw_cmd.data += buf->y_len - 1;
JPEG_DBG("%s:%d: MAX DMA addr %08x , reg offset %08x , length %d\n",
__func__, __LINE__, tmp_hw_cmd.data, tmp_hw_cmd.offset,
buf->y_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_dma_cmd_we_mmu_prefetch[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_S1_MMU_PF_ADDR_MIN,
MSM_JPEGDMA_S1_MMU_PF_ADDR_MIN_BMSK, {0} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, MSM_JPEGDMA_S1_MMU_PF_ADDR_MAX,
MSM_JPEGDMA_S1_MMU_PF_ADDR_MAX_BMSK, {0} },
};
/*
* msm_jpegdma_hw_we_mmu_prefetch() - write DMA we min/max addrs to
* MMU prefetch registers.
* @buf: Pointer to jpeg hw buffer.
* @base: Pointer to base address.
*
* This function writes DMA we min/max address for each plane to MMU prefetch
* registers, MMU prefetch hardware will only prefetch address translations
* with in this min/max boundary.
*
* Return: None.
*/
void msm_jpegdma_hw_we_mmu_prefetch(struct msm_jpeg_hw_buf *buf, void *base)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
struct msm_jpeg_hw_cmd tmp_hw_cmd;
hw_cmd_p = &hw_dma_cmd_we_mmu_prefetch[0];
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
JPEG_DBG("%s:%d: MIN DMA addr %08x , reg offset %08x\n",
__func__, __LINE__, tmp_hw_cmd.data, tmp_hw_cmd.offset);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(&tmp_hw_cmd, base);
tmp_hw_cmd = *hw_cmd_p++;
tmp_hw_cmd.data = buf->y_buffer_addr;
if (buf->y_len)
tmp_hw_cmd.data += buf->y_len - 1;
JPEG_DBG("%s:%d: MAX DMA addr %08x , reg offset %08x , length %d\n",
__func__, __LINE__, tmp_hw_cmd.data, tmp_hw_cmd.offset,
buf->y_len);
msm_jpeg_hw_write(&tmp_hw_cmd, base);
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_cmd_reset[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_DISABLE_ALL} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_CLEAR_ADDR,
JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_CLEAR_ALL} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_RESET_CMD_ADDR,
JPEG_RESET_CMD_RMSK, {JPEG_RESET_DEFAULT} },
};
void msm_jpeg_hw_reset(void *base, int size)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
hw_cmd_p = &hw_cmd_reset[0];
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p, base);
/* ensure write is done */
wmb();
}
static struct msm_jpeg_hw_cmd hw_cmd_reset_dma[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_IRQ_MASK_ADDR,
JPEGDMA_IRQ_MASK_BMSK, {JPEGDMA_IRQ_DISABLE_ALL} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_IRQ_CLEAR_ADDR,
JPEGDMA_IRQ_MASK_BMSK, {JPEGDMA_IRQ_CLEAR_ALL} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_IRQ_MASK_ADDR,
JPEGDMA_IRQ_MASK_BMSK, {JPEGDMA_IRQ_ALLSOURCES_ENABLE} },
{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEGDMA_RESET_CMD_ADDR,
JPEGDMA_RESET_CMD_BMSK, {JPEGDMA_RESET_DEFAULT} },
};
void msm_jpeg_hw_reset_dma(void *base, int size)
{
struct msm_jpeg_hw_cmd *hw_cmd_p;
hw_cmd_p = &hw_cmd_reset_dma[0];
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p++, base);
/* ensure write is done */
wmb();
msm_jpeg_hw_write(hw_cmd_p, base);
/* ensure write is done */
wmb();
}
uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p,
void *jpeg_region_base)
{
uint32_t *paddr;
uint32_t data;
paddr = jpeg_region_base + hw_cmd_p->offset;
data = msm_camera_io_r((void __iomem *)paddr);
data &= hw_cmd_p->mask;
return data;
}
void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p,
void *jpeg_region_base)
{
uint32_t *paddr;
uint32_t old_data, new_data;
paddr = jpeg_region_base + hw_cmd_p->offset;
if (hw_cmd_p->mask == 0xffffffff) {
old_data = 0;
} else {
old_data = msm_camera_io_r((void __iomem *)paddr);
old_data &= ~hw_cmd_p->mask;
}
new_data = hw_cmd_p->data & hw_cmd_p->mask;
new_data |= old_data;
JPEG_DBG("%s:%d] %pK %08x\n", __func__, __LINE__,
paddr, new_data);
msm_camera_io_w(new_data, (void __iomem *)paddr);
}
int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us,
void *base)
{
int tm = hw_cmd_p->n;
uint32_t data;
uint32_t wait_data = hw_cmd_p->data & hw_cmd_p->mask;
data = msm_jpeg_hw_read(hw_cmd_p, base);
if (data != wait_data) {
while (tm) {
udelay(m_us);
data = msm_jpeg_hw_read(hw_cmd_p, base);
if (data == wait_data)
break;
tm--;
}
}
hw_cmd_p->data = data;
return tm;
}
void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us)
{
int tm = hw_cmd_p->n;
while (tm) {
udelay(m_us);
tm--;
}
}
int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, uint32_t m_cmds,
uint32_t max_size, void *base)
{
int is_copy_to_user = 0;
uint32_t data;
while (m_cmds--) {
if (hw_cmd_p->offset >= max_size) {
JPEG_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__,
__LINE__, hw_cmd_p->offset, max_size);
return -EFAULT;
}
if (hw_cmd_p->offset & 0x3) {
JPEG_PR_ERR("%s:%d] %d Invalid alignment\n", __func__,
__LINE__, hw_cmd_p->offset);
return -EFAULT;
}
switch (hw_cmd_p->type) {
case MSM_JPEG_HW_CMD_TYPE_READ:
hw_cmd_p->data = msm_jpeg_hw_read(hw_cmd_p, base);
is_copy_to_user = 1;
break;
case MSM_JPEG_HW_CMD_TYPE_WRITE:
msm_jpeg_hw_write(hw_cmd_p, base);
break;
case MSM_JPEG_HW_CMD_TYPE_WRITE_OR:
data = msm_jpeg_hw_read(hw_cmd_p, base);
hw_cmd_p->data = (hw_cmd_p->data & hw_cmd_p->mask) |
data;
msm_jpeg_hw_write(hw_cmd_p, base);
break;
case MSM_JPEG_HW_CMD_TYPE_UWAIT:
msm_jpeg_hw_wait(hw_cmd_p, 1, base);
break;
case MSM_JPEG_HW_CMD_TYPE_MWAIT:
msm_jpeg_hw_wait(hw_cmd_p, 1000, base);
break;
case MSM_JPEG_HW_CMD_TYPE_UDELAY:
msm_jpeg_hw_delay(hw_cmd_p, 1);
break;
case MSM_JPEG_HW_CMD_TYPE_MDELAY:
msm_jpeg_hw_delay(hw_cmd_p, 1000);
break;
default:
JPEG_PR_ERR("wrong hw command type\n");
break;
}
hw_cmd_p++;
}
return is_copy_to_user;
}
void msm_jpeg_io_dump(void *base, int size)
{
char line_str[128];
void __iomem *addr = (void __iomem *)base;
int i;
void __iomem *p = addr;
size_t offset = 0;
size_t used = 0;
size_t min_range = 0;
size_t sizeof_line_str = sizeof(line_str);
u32 data;
JPEG_DBG_HIGH("%s:%d] %pK %d", __func__, __LINE__, addr, size);
line_str[0] = '\0';
for (i = 0; i < size/4; i++) {
if (i % 4 == 0) {
used = snprintf(line_str + offset,
sizeof_line_str - offset, "%pK ", p);
if ((used < min_range) ||
(offset + used >= sizeof_line_str)) {
JPEG_PR_ERR("%s\n", line_str);
offset = 0;
line_str[0] = '\0';
} else {
offset += used;
}
}
data = msm_camera_io_r(p++);
used = snprintf(line_str + offset,
sizeof_line_str - offset, "%08x ", data);
if ((used < min_range) ||
(offset + used >= sizeof_line_str)) {
JPEG_PR_ERR("%s\n", line_str);
offset = 0;
line_str[0] = '\0';
} else {
offset += used;
}
if ((i + 1) % 4 == 0) {
JPEG_DBG_HIGH("%s\n", line_str);
line_str[0] = '\0';
offset = 0;
}
}
if (line_str[0] != '\0')
JPEG_DBG_HIGH("%s\n", line_str);
}