293 lines
7.0 KiB
C
293 lines
7.0 KiB
C
/*
|
|
* Copyright 2018 NXP
|
|
*
|
|
* 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 <video/dpu.h>
|
|
#include "dpu-prv.h"
|
|
|
|
#define BASEADDRESS(n) (0x10 + (n) * 0x28)
|
|
#define SOURCEBUFFERATTRIBUTES(n) (0x14 + (n) * 0x28)
|
|
#define SOURCEBUFFERDIMENSION(n) (0x18 + (n) * 0x28)
|
|
#define COLORCOMPONENTBITS(n) (0x1C + (n) * 0x28)
|
|
#define COLORCOMPONENTSHIFT(n) (0x20 + (n) * 0x28)
|
|
#define LAYEROFFSET(n) (0x24 + (n) * 0x28)
|
|
#define CLIPWINDOWOFFSET(n) (0x28 + (n) * 0x28)
|
|
#define CLIPWINDOWDIMENSIONS(n) (0x2C + (n) * 0x28)
|
|
#define CONSTANTCOLOR(n) (0x30 + (n) * 0x28)
|
|
#define LAYERPROPERTY(n) (0x34 + (n) * 0x28)
|
|
|
|
void fetchunit_get_dprc(struct dpu_fetchunit *fu, void *data)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return;
|
|
|
|
fu->dprc = data;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_get_dprc);
|
|
|
|
void fetchunit_shden(struct dpu_fetchunit *fu, bool enable)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, STATICCONTROL);
|
|
if (enable)
|
|
val |= SHDEN;
|
|
else
|
|
val &= ~SHDEN;
|
|
dpu_fu_write(fu, val, STATICCONTROL);
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_shden);
|
|
|
|
void fetchunit_baddr_autoupdate(struct dpu_fetchunit *fu, u8 layer_mask)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, STATICCONTROL);
|
|
val &= ~BASEADDRESSAUTOUPDATE_MASK;
|
|
val |= BASEADDRESSAUTOUPDATE(layer_mask);
|
|
dpu_fu_write(fu, val, STATICCONTROL);
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_baddr_autoupdate);
|
|
|
|
void fetchunit_shdldreq_sticky(struct dpu_fetchunit *fu, u8 layer_mask)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, STATICCONTROL);
|
|
val &= ~SHDLDREQSTICKY_MASK;
|
|
val |= SHDLDREQSTICKY(layer_mask);
|
|
dpu_fu_write(fu, val, STATICCONTROL);
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_shdldreq_sticky);
|
|
|
|
void fetchunit_set_burstlength(struct dpu_fetchunit *fu, dma_addr_t baddr,
|
|
bool use_prefetch)
|
|
{
|
|
struct dpu_soc *dpu = fu->dpu;
|
|
unsigned int burst_size, burst_length;
|
|
u32 val;
|
|
|
|
if (use_prefetch) {
|
|
/*
|
|
* address TKT343664:
|
|
* fetch unit base address has to align to burst size
|
|
*/
|
|
burst_size = 1 << (ffs(baddr) - 1);
|
|
burst_size = min(burst_size, 128U);
|
|
burst_length = burst_size / 8;
|
|
} else {
|
|
burst_length = 16;
|
|
}
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, BURSTBUFFERMANAGEMENT);
|
|
val &= ~SETBURSTLENGTH_MASK;
|
|
val |= SETBURSTLENGTH(burst_length);
|
|
dpu_fu_write(fu, val, BURSTBUFFERMANAGEMENT);
|
|
mutex_unlock(&fu->mutex);
|
|
|
|
dev_dbg(dpu->dev, "%s%d burst length is %u\n",
|
|
fu->name, fu->id, burst_length);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_set_burstlength);
|
|
|
|
void fetchunit_set_baseaddress(struct dpu_fetchunit *fu, dma_addr_t paddr)
|
|
{
|
|
mutex_lock(&fu->mutex);
|
|
dpu_fu_write(fu, paddr, BASEADDRESS(fu->sub_id));
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_set_baseaddress);
|
|
|
|
void fetchunit_set_src_bpp(struct dpu_fetchunit *fu, int bpp)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, SOURCEBUFFERATTRIBUTES(fu->sub_id));
|
|
val &= ~0x3f0000;
|
|
val |= BITSPERPIXEL(bpp);
|
|
dpu_fu_write(fu, val, SOURCEBUFFERATTRIBUTES(fu->sub_id));
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_set_src_bpp);
|
|
|
|
/*
|
|
* The arguments width and bpp are valid only when use_prefetch is true.
|
|
* For fetcheco, since the pixel format has to be NV12 or NV21 when
|
|
* use_prefetch is true, we assume width stands for how many UV we have
|
|
* in bytes for one line, while bpp should be 8bits for every U or V component.
|
|
*/
|
|
void fetchunit_set_src_stride(struct dpu_fetchunit *fu,
|
|
unsigned int width, int bpp, unsigned int stride,
|
|
dma_addr_t baddr, bool use_prefetch)
|
|
{
|
|
unsigned int burst_size;
|
|
u32 val;
|
|
|
|
if (use_prefetch) {
|
|
/*
|
|
* address TKT343664:
|
|
* fetch unit base address has to align to burst size
|
|
*/
|
|
burst_size = 1 << (ffs(baddr) - 1);
|
|
burst_size = min(burst_size, 128U);
|
|
|
|
stride = width * (bpp >> 3);
|
|
/*
|
|
* address TKT339017:
|
|
* fixup for burst size vs stride mismatch
|
|
*/
|
|
stride = round_up(stride, burst_size);
|
|
}
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, SOURCEBUFFERATTRIBUTES(fu->sub_id));
|
|
val &= ~0xffff;
|
|
val |= STRIDE(stride);
|
|
dpu_fu_write(fu, val, SOURCEBUFFERATTRIBUTES(fu->sub_id));
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_set_src_stride);
|
|
|
|
void fetchunit_enable_src_buf(struct dpu_fetchunit *fu)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id));
|
|
val |= SOURCEBUFFERENABLE;
|
|
dpu_fu_write(fu, val, LAYERPROPERTY(fu->sub_id));
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_enable_src_buf);
|
|
|
|
void fetchunit_disable_src_buf(struct dpu_fetchunit *fu)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id));
|
|
val &= ~SOURCEBUFFERENABLE;
|
|
dpu_fu_write(fu, val, LAYERPROPERTY(fu->sub_id));
|
|
mutex_unlock(&fu->mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_disable_src_buf);
|
|
|
|
bool fetchunit_is_enabled(struct dpu_fetchunit *fu)
|
|
{
|
|
u32 val;
|
|
|
|
mutex_lock(&fu->mutex);
|
|
val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id));
|
|
mutex_unlock(&fu->mutex);
|
|
|
|
return !!(val & SOURCEBUFFERENABLE);
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_is_enabled);
|
|
|
|
unsigned int fetchunit_get_stream_id(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return DPU_PLANE_SRC_DISABLED;
|
|
|
|
return fu->stream_id;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_get_stream_id);
|
|
|
|
void fetchunit_set_stream_id(struct dpu_fetchunit *fu, unsigned int id)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return;
|
|
|
|
switch (id) {
|
|
case DPU_PLANE_SRC_TO_DISP_STREAM0:
|
|
case DPU_PLANE_SRC_TO_DISP_STREAM1:
|
|
case DPU_PLANE_SRC_DISABLED:
|
|
fu->stream_id = id;
|
|
break;
|
|
default:
|
|
WARN_ON(1);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_set_stream_id);
|
|
|
|
void fetchunit_pin_off(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return;
|
|
|
|
fu->pin_off = true;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_pin_off);
|
|
|
|
void fetchunit_unpin_off(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return;
|
|
|
|
fu->pin_off = false;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_unpin_off);
|
|
|
|
bool fetchunit_is_pinned_off(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return false;
|
|
|
|
return fu->pin_off;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_is_pinned_off);
|
|
|
|
bool fetchunit_is_fetchdecode(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return false;
|
|
|
|
return fu->type == FU_T_FD;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_is_fetchdecode);
|
|
|
|
bool fetchunit_is_fetcheco(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return false;
|
|
|
|
return fu->type == FU_T_FE;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_is_fetcheco);
|
|
|
|
bool fetchunit_is_fetchlayer(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return false;
|
|
|
|
return fu->type == FU_T_FL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_is_fetchlayer);
|
|
|
|
bool fetchunit_is_fetchwarp(struct dpu_fetchunit *fu)
|
|
{
|
|
if (WARN_ON(!fu))
|
|
return false;
|
|
|
|
return fu->type == FU_T_FW;
|
|
}
|
|
EXPORT_SYMBOL_GPL(fetchunit_is_fetchwarp);
|