Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
4c5b1fb8
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
4c5b1fb8
编写于
7月 25, 2012
作者:
F
Florian Tobias Schandinat
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-next' of
git://linuxtv.org/pinchartl/fbdev
into fbdev-next
上级
a2c81bc1
a4aa25f6
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
293 addition
and
227 deletion
+293
-227
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_lcdcfb.c
+107
-102
drivers/video/sh_mobile_lcdcfb.h
drivers/video/sh_mobile_lcdcfb.h
+3
-2
drivers/video/sh_mobile_meram.c
drivers/video/sh_mobile_meram.c
+132
-103
include/video/sh_mobile_meram.h
include/video/sh_mobile_meram.h
+51
-20
未找到文件。
drivers/video/sh_mobile_lcdcfb.c
浏览文件 @
4c5b1fb8
...
...
@@ -161,7 +161,7 @@ enum sh_mobile_lcdc_overlay_mode {
* @dma_handle: Frame buffer DMA address
* @base_addr_y: Overlay base address (RGB or luma component)
* @base_addr_c: Overlay base address (chroma component)
* @pan_
offset: Current pan offset in bytes
* @pan_
y_offset: Panning linear offset in bytes (luma component)
* @format: Current pixelf format
* @xres: Horizontal visible resolution
* @xres_virtual: Horizontal total resolution
...
...
@@ -191,7 +191,7 @@ struct sh_mobile_lcdc_overlay {
dma_addr_t
dma_handle
;
unsigned
long
base_addr_y
;
unsigned
long
base_addr_c
;
unsigned
long
pan_offset
;
unsigned
long
pan_
y_
offset
;
const
struct
sh_mobile_lcdc_format_info
*
format
;
unsigned
int
xres
;
...
...
@@ -873,8 +873,8 @@ static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
}
ovl
->
base_addr_y
=
ovl
->
dma_handle
;
ovl
->
base_addr_c
=
ovl
->
base_addr_y
+
ovl
->
xres
*
ovl
->
yres_virtual
;
ovl
->
base_addr_c
=
ovl
->
dma_handle
+
ovl
->
xres_virtual
*
ovl
->
yres_virtual
;
switch
(
ovl
->
mode
)
{
case
LCDC_OVERLAY_BLEND
:
...
...
@@ -1104,27 +1104,25 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
/* Compute frame buffer base address and pitch for each channel. */
for
(
k
=
0
;
k
<
ARRAY_SIZE
(
priv
->
ch
);
k
++
)
{
int
pixelformat
;
void
*
meram
;
void
*
cache
;
ch
=
&
priv
->
ch
[
k
];
if
(
!
ch
->
enabled
)
continue
;
ch
->
base_addr_y
=
ch
->
dma_handle
;
ch
->
base_addr_c
=
ch
->
base_addr_y
+
ch
->
xres
*
ch
->
yres_virtual
;
ch
->
base_addr_c
=
ch
->
dma_handle
+
ch
->
xres_virtual
*
ch
->
yres_virtual
;
ch
->
line_size
=
ch
->
pitch
;
/* Enable MERAM if possible. */
if
(
mdev
==
NULL
||
mdev
->
ops
==
NULL
||
ch
->
cfg
->
meram_cfg
==
NULL
)
if
(
mdev
==
NULL
||
ch
->
cfg
->
meram_cfg
==
NULL
)
continue
;
/* we need to de-init configured ICBs before we can
* re-initialize them.
*/
if
(
ch
->
meram
)
{
mdev
->
ops
->
meram_unregister
(
mdev
,
ch
->
meram
);
ch
->
meram
=
NULL
;
/* Free the allocated MERAM cache. */
if
(
ch
->
cache
)
{
sh_mobile_meram_cache_free
(
mdev
,
ch
->
cache
);
ch
->
cache
=
NULL
;
}
switch
(
ch
->
format
->
fourcc
)
{
...
...
@@ -1146,14 +1144,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
break
;
}
meram
=
mdev
->
ops
->
meram_register
(
mdev
,
ch
->
cfg
->
meram_cfg
,
cache
=
sh_mobile_meram_cache_alloc
(
mdev
,
ch
->
cfg
->
meram_cfg
,
ch
->
pitch
,
ch
->
yres
,
pixelformat
,
&
ch
->
line_size
);
if
(
!
IS_ERR
(
meram
))
{
mdev
->
ops
->
meram_update
(
mdev
,
meram
,
if
(
!
IS_ERR
(
cache
))
{
sh_mobile_meram_cache_update
(
mdev
,
cache
,
ch
->
base_addr_y
,
ch
->
base_addr_c
,
&
ch
->
base_addr_y
,
&
ch
->
base_addr_c
);
ch
->
meram
=
meram
;
ch
->
cache
=
cache
;
}
}
...
...
@@ -1223,12 +1221,10 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
sh_mobile_lcdc_display_off
(
ch
);
/* disable the meram */
if
(
ch
->
meram
)
{
struct
sh_mobile_meram_info
*
mdev
;
mdev
=
priv
->
meram_dev
;
mdev
->
ops
->
meram_unregister
(
mdev
,
ch
->
meram
);
ch
->
meram
=
0
;
/* Free the MERAM cache. */
if
(
ch
->
cache
)
{
sh_mobile_meram_cache_free
(
priv
->
meram_dev
,
ch
->
cache
);
ch
->
cache
=
0
;
}
}
...
...
@@ -1498,7 +1494,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = {
.
type
=
FB_TYPE_PACKED_PIXELS
,
.
visual
=
FB_VISUAL_TRUECOLOR
,
.
accel
=
FB_ACCEL_NONE
,
.
xpanstep
=
0
,
.
xpanstep
=
1
,
.
ypanstep
=
1
,
.
ywrapstep
=
0
,
.
capabilities
=
FB_CAP_FOURCC
,
...
...
@@ -1510,44 +1506,44 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
struct
sh_mobile_lcdc_overlay
*
ovl
=
info
->
par
;
unsigned
long
base_addr_y
;
unsigned
long
base_addr_c
;
unsigned
long
pan
_offset
;
unsigned
long
y
_offset
;
unsigned
long
c_offset
;
if
(
!
ovl
->
format
->
yuv
)
pan_offset
=
var
->
yoffset
*
ovl
->
pitch
+
var
->
xoffset
*
(
ovl
->
format
->
bpp
/
8
);
else
pan_offset
=
var
->
yoffset
*
ovl
->
pitch
+
var
->
xoffset
;
if
(
!
ovl
->
format
->
yuv
)
{
y_offset
=
(
var
->
yoffset
*
ovl
->
xres_virtual
+
var
->
xoffset
)
*
ovl
->
format
->
bpp
/
8
;
c_offset
=
0
;
}
else
{
unsigned
int
xsub
=
ovl
->
format
->
bpp
<
24
?
2
:
1
;
unsigned
int
ysub
=
ovl
->
format
->
bpp
<
16
?
2
:
1
;
y_offset
=
var
->
yoffset
*
ovl
->
xres_virtual
+
var
->
xoffset
;
c_offset
=
var
->
yoffset
/
ysub
*
ovl
->
xres_virtual
*
2
/
xsub
+
var
->
xoffset
*
2
/
xsub
;
}
if
(
pan_offset
==
ovl
->
pan_offset
)
return
0
;
/* No change, do nothing */
/* If the Y offset hasn't changed, the C offset hasn't either. There's
* nothing to do in that case.
*/
if
(
y_offset
==
ovl
->
pan_y_offset
)
return
0
;
/* Set the source address for the next refresh */
base_addr_y
=
ovl
->
dma_handle
+
pan_offset
;
base_addr_y
=
ovl
->
dma_handle
+
y_offset
;
base_addr_c
=
ovl
->
dma_handle
+
ovl
->
xres_virtual
*
ovl
->
yres_virtual
+
c_offset
;
ovl
->
base_addr_y
=
base_addr_y
;
ovl
->
base_addr_c
=
base_addr_y
;
ovl
->
base_addr_c
=
base_addr_c
;
ovl
->
pan_y_offset
=
y_offset
;
if
(
ovl
->
format
->
yuv
)
{
/* Set Y offset */
c_offset
=
var
->
yoffset
*
ovl
->
pitch
*
(
ovl
->
format
->
bpp
-
8
)
/
8
;
base_addr_c
=
ovl
->
dma_handle
+
ovl
->
xres
*
ovl
->
yres_virtual
+
c_offset
;
/* Set X offset */
if
(
ovl
->
format
->
fourcc
==
V4L2_PIX_FMT_NV24
)
base_addr_c
+=
2
*
var
->
xoffset
;
else
base_addr_c
+=
var
->
xoffset
;
ovl
->
base_addr_c
=
base_addr_c
;
}
lcdc_write
(
ovl
->
channel
->
lcdc
,
LDBCR
,
LDBCR_UPC
(
ovl
->
index
));
lcdc_write_overlay
(
ovl
,
LDBnBSAYR
(
ovl
->
index
),
ovl
->
base_addr_y
);
lcdc_write_overlay
(
ovl
,
LDBnBSACR
(
ovl
->
index
),
ovl
->
base_addr_c
);
ovl
->
pan_offset
=
pan_offset
;
lcdc_write
(
ovl
->
channel
->
lcdc
,
LDBCR
,
LDBCR_UPF
(
ovl
->
index
)
|
LDBCR_UPD
(
ovl
->
index
));
return
0
;
}
...
...
@@ -1585,9 +1581,9 @@ static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
ovl
->
yres_virtual
=
info
->
var
.
yres_virtual
;
if
(
ovl
->
format
->
yuv
)
ovl
->
pitch
=
info
->
var
.
xres
;
ovl
->
pitch
=
info
->
var
.
xres
_virtual
;
else
ovl
->
pitch
=
info
->
var
.
xres
*
ovl
->
format
->
bpp
/
8
;
ovl
->
pitch
=
info
->
var
.
xres
_virtual
*
ovl
->
format
->
bpp
/
8
;
sh_mobile_lcdc_overlay_setup
(
ovl
);
...
...
@@ -1719,9 +1715,14 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
else
info
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
if
(
ovl
->
format
->
fourcc
==
V4L2_PIX_FMT_NV12
||
ovl
->
format
->
fourcc
==
V4L2_PIX_FMT_NV21
)
switch
(
ovl
->
format
->
fourcc
)
{
case
V4L2_PIX_FMT_NV16
:
case
V4L2_PIX_FMT_NV61
:
info
->
fix
.
ypanstep
=
2
;
case
V4L2_PIX_FMT_NV12
:
case
V4L2_PIX_FMT_NV21
:
info
->
fix
.
xpanstep
=
2
;
}
/* Initialize variable screen information. */
var
=
&
info
->
var
;
...
...
@@ -1776,7 +1777,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
.
type
=
FB_TYPE_PACKED_PIXELS
,
.
visual
=
FB_VISUAL_TRUECOLOR
,
.
accel
=
FB_ACCEL_NONE
,
.
xpanstep
=
0
,
.
xpanstep
=
1
,
.
ypanstep
=
1
,
.
ywrapstep
=
0
,
.
capabilities
=
FB_CAP_FOURCC
,
...
...
@@ -1809,58 +1810,53 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
struct
sh_mobile_lcdc_chan
*
ch
=
info
->
par
;
struct
sh_mobile_lcdc_priv
*
priv
=
ch
->
lcdc
;
unsigned
long
ldrcntr
;
unsigned
long
new_pan_offset
;
unsigned
long
base_addr_y
,
base_addr_c
;
unsigned
long
y_offset
;
unsigned
long
c_offset
;
if
(
!
ch
->
format
->
yuv
)
new_pan_offset
=
var
->
yoffset
*
ch
->
pitch
+
var
->
xoffset
*
(
ch
->
format
->
bpp
/
8
);
else
new_pan_offset
=
var
->
yoffset
*
ch
->
pitch
+
var
->
xoffset
;
if
(
!
ch
->
format
->
yuv
)
{
y_offset
=
(
var
->
yoffset
*
ch
->
xres_virtual
+
var
->
xoffset
)
*
ch
->
format
->
bpp
/
8
;
c_offset
=
0
;
}
else
{
unsigned
int
xsub
=
ch
->
format
->
bpp
<
24
?
2
:
1
;
unsigned
int
ysub
=
ch
->
format
->
bpp
<
16
?
2
:
1
;
if
(
new_pan_offset
==
ch
->
pan_offset
)
return
0
;
/* No change, do nothing */
y_offset
=
var
->
yoffset
*
ch
->
xres_virtual
+
var
->
xoffset
;
c_offset
=
var
->
yoffset
/
ysub
*
ch
->
xres_virtual
*
2
/
xsub
+
var
->
xoffset
*
2
/
xsub
;
}
ldrcntr
=
lcdc_read
(
priv
,
_LDRCNTR
);
/* If the Y offset hasn't changed, the C offset hasn't either. There's
* nothing to do in that case.
*/
if
(
y_offset
==
ch
->
pan_y_offset
)
return
0
;
/* Set the source address for the next refresh */
base_addr_y
=
ch
->
dma_handle
+
new_pan_offset
;
if
(
ch
->
format
->
yuv
)
{
/* Set y offset */
c_offset
=
var
->
yoffset
*
ch
->
pitch
*
(
ch
->
format
->
bpp
-
8
)
/
8
;
base_addr_c
=
ch
->
dma_handle
+
ch
->
xres
*
ch
->
yres_virtual
+
c_offset
;
/* Set x offset */
if
(
ch
->
format
->
fourcc
==
V4L2_PIX_FMT_NV24
)
base_addr_c
+=
2
*
var
->
xoffset
;
else
base_addr_c
+=
var
->
xoffset
;
}
base_addr_y
=
ch
->
dma_handle
+
y_offset
;
base_addr_c
=
ch
->
dma_handle
+
ch
->
xres_virtual
*
ch
->
yres_virtual
+
c_offset
;
if
(
ch
->
meram
)
{
struct
sh_mobile_meram_info
*
mdev
;
mdev
=
priv
->
meram_dev
;
mdev
->
ops
->
meram_update
(
mdev
,
ch
->
meram
,
base_addr_y
,
base_addr_c
,
&
base_addr_y
,
&
base_addr_c
);
}
if
(
ch
->
cache
)
sh_mobile_meram_cache_update
(
priv
->
meram_dev
,
ch
->
cache
,
base_addr_y
,
base_addr_c
,
&
base_addr_y
,
&
base_addr_c
);
ch
->
base_addr_y
=
base_addr_y
;
ch
->
base_addr_c
=
base_addr_c
;
ch
->
pan_y_offset
=
y_offset
;
lcdc_write_chan_mirror
(
ch
,
LDSA1R
,
base_addr_y
);
if
(
ch
->
format
->
yuv
)
lcdc_write_chan_mirror
(
ch
,
LDSA2R
,
base_addr_c
);
ldrcntr
=
lcdc_read
(
priv
,
_LDRCNTR
);
if
(
lcdc_chan_is_sublcd
(
ch
))
lcdc_write
(
ch
->
lcdc
,
_LDRCNTR
,
ldrcntr
^
LDRCNTR_SRS
);
else
lcdc_write
(
ch
->
lcdc
,
_LDRCNTR
,
ldrcntr
^
LDRCNTR_MRS
);
ch
->
pan_offset
=
new_pan_offset
;
sh_mobile_lcdc_deferred_io_touch
(
info
);
...
...
@@ -2033,9 +2029,9 @@ static int sh_mobile_lcdc_set_par(struct fb_info *info)
ch
->
yres_virtual
=
info
->
var
.
yres_virtual
;
if
(
ch
->
format
->
yuv
)
ch
->
pitch
=
info
->
var
.
xres
;
ch
->
pitch
=
info
->
var
.
xres
_virtual
;
else
ch
->
pitch
=
info
->
var
.
xres
*
ch
->
format
->
bpp
/
8
;
ch
->
pitch
=
info
->
var
.
xres
_virtual
*
ch
->
format
->
bpp
/
8
;
ret
=
sh_mobile_lcdc_start
(
ch
->
lcdc
);
if
(
ret
<
0
)
...
...
@@ -2218,19 +2214,24 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
else
info
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
if
(
ch
->
format
->
fourcc
==
V4L2_PIX_FMT_NV12
||
ch
->
format
->
fourcc
==
V4L2_PIX_FMT_NV21
)
switch
(
ch
->
format
->
fourcc
)
{
case
V4L2_PIX_FMT_NV16
:
case
V4L2_PIX_FMT_NV61
:
info
->
fix
.
ypanstep
=
2
;
case
V4L2_PIX_FMT_NV12
:
case
V4L2_PIX_FMT_NV21
:
info
->
fix
.
xpanstep
=
2
;
}
/* Initialize variable screen information using the first mode as
* default. The default Y virtual resolution is twice the panel size to
* allow for double-buffering.
* default.
*/
var
=
&
info
->
var
;
fb_videomode_to_var
(
var
,
mode
);
var
->
width
=
ch
->
cfg
->
panel_cfg
.
width
;
var
->
height
=
ch
->
cfg
->
panel_cfg
.
height
;
var
->
yres_virtual
=
var
->
yres
*
2
;
var
->
xres_virtual
=
ch
->
xres_virtual
;
var
->
yres_virtual
=
ch
->
yres_virtual
;
var
->
activate
=
FB_ACTIVATE_NOW
;
/* Use the legacy API by default for RGB formats, and the FOURCC API
...
...
@@ -2453,8 +2454,11 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
priv
->
ch
);
i
++
)
{
if
(
priv
->
ch
[
i
].
bl
)
sh_mobile_lcdc_bl_remove
(
priv
->
ch
[
i
].
bl
);
struct
sh_mobile_lcdc_chan
*
ch
=
&
priv
->
ch
[
i
];
if
(
ch
->
bl
)
sh_mobile_lcdc_bl_remove
(
ch
->
bl
);
mutex_destroy
(
&
ch
->
open_lock
);
}
if
(
priv
->
dot_clk
)
{
...
...
@@ -2545,9 +2549,9 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
ovl
->
yres_virtual
=
ovl
->
yres
*
2
;
if
(
!
format
->
yuv
)
ovl
->
pitch
=
ovl
->
xres
*
format
->
bpp
/
8
;
ovl
->
pitch
=
ovl
->
xres
_virtual
*
format
->
bpp
/
8
;
else
ovl
->
pitch
=
ovl
->
xres
;
ovl
->
pitch
=
ovl
->
xres
_virtual
;
/* Allocate frame buffer memory. */
ovl
->
fb_size
=
ovl
->
cfg
->
max_xres
*
ovl
->
cfg
->
max_yres
...
...
@@ -2625,7 +2629,9 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
num_modes
=
cfg
->
num_modes
;
}
/* Use the first mode as default. */
/* Use the first mode as default. The default Y virtual resolution is
* twice the panel size to allow for double-buffering.
*/
ch
->
format
=
format
;
ch
->
xres
=
mode
->
xres
;
ch
->
xres_virtual
=
mode
->
xres
;
...
...
@@ -2634,10 +2640,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
if
(
!
format
->
yuv
)
{
ch
->
colorspace
=
V4L2_COLORSPACE_SRGB
;
ch
->
pitch
=
ch
->
xres
*
format
->
bpp
/
8
;
ch
->
pitch
=
ch
->
xres
_virtual
*
format
->
bpp
/
8
;
}
else
{
ch
->
colorspace
=
V4L2_COLORSPACE_REC709
;
ch
->
pitch
=
ch
->
xres
;
ch
->
pitch
=
ch
->
xres
_virtual
;
}
ch
->
display
.
width
=
cfg
->
panel_cfg
.
width
;
...
...
@@ -2723,7 +2729,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
}
init_waitqueue_head
(
&
ch
->
frame_end_wait
);
init_completion
(
&
ch
->
vsync_completion
);
ch
->
pan_offset
=
0
;
/* probe the backlight is there is one defined */
if
(
ch
->
cfg
->
bl_info
.
max_brightness
)
...
...
drivers/video/sh_mobile_lcdcfb.h
浏览文件 @
4c5b1fb8
...
...
@@ -47,6 +47,7 @@ struct sh_mobile_lcdc_entity {
/*
* struct sh_mobile_lcdc_chan - LCDC display channel
*
* @pan_y_offset: Panning linear offset in bytes (luma component)
* @base_addr_y: Frame buffer viewport base address (luma component)
* @base_addr_c: Frame buffer viewport base address (chroma component)
* @pitch: Frame buffer line pitch
...
...
@@ -59,7 +60,7 @@ struct sh_mobile_lcdc_chan {
unsigned
long
*
reg_offs
;
unsigned
long
ldmt1r_value
;
unsigned
long
enabled
;
/* ME and SE in LDCNT2R */
void
*
meram
;
void
*
cache
;
struct
mutex
open_lock
;
/* protects the use counter */
int
use_count
;
...
...
@@ -68,7 +69,7 @@ struct sh_mobile_lcdc_chan {
unsigned
long
fb_size
;
dma_addr_t
dma_handle
;
unsigned
long
pan_offset
;
unsigned
long
pan_
y_
offset
;
unsigned
long
frame_end
;
wait_queue_head_t
frame_end_wait
;
...
...
drivers/video/sh_mobile_meram.c
浏览文件 @
4c5b1fb8
...
...
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/genalloc.h>
#include <linux/io.h>
#include <linux/kernel.h>
...
...
@@ -194,13 +195,28 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
}
/* -----------------------------------------------------------------------------
* Allocation
* MERAM allocation and free
*/
static
unsigned
long
meram_alloc
(
struct
sh_mobile_meram_priv
*
priv
,
size_t
size
)
{
return
gen_pool_alloc
(
priv
->
pool
,
size
);
}
static
void
meram_free
(
struct
sh_mobile_meram_priv
*
priv
,
unsigned
long
mem
,
size_t
size
)
{
gen_pool_free
(
priv
->
pool
,
mem
,
size
);
}
/* -----------------------------------------------------------------------------
* LCDC cache planes allocation, init, cleanup and free
*/
/* Allocate ICBs and MERAM for a plane. */
static
int
__meram
_alloc
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
,
size_t
size
)
static
int
meram_plane
_alloc
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
,
size_t
size
)
{
unsigned
long
mem
;
unsigned
long
idx
;
...
...
@@ -215,7 +231,7 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
return
-
ENOMEM
;
plane
->
marker
=
&
priv
->
icbs
[
idx
];
mem
=
gen_pool_alloc
(
priv
->
pool
,
size
*
1024
);
mem
=
meram_alloc
(
priv
,
size
*
1024
);
if
(
mem
==
0
)
return
-
ENOMEM
;
...
...
@@ -229,11 +245,11 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
}
/* Free ICBs and MERAM for a plane. */
static
void
__meram
_free
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
)
static
void
meram_plane
_free
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
)
{
gen_pool_free
(
priv
->
pool
,
priv
->
meram
+
plane
->
marker
->
offset
,
plane
->
marker
->
size
*
1024
);
meram_free
(
priv
,
priv
->
meram
+
plane
->
marker
->
offset
,
plane
->
marker
->
size
*
1024
);
__clear_bit
(
plane
->
marker
->
index
,
&
priv
->
used_icb
);
__clear_bit
(
plane
->
cache
->
index
,
&
priv
->
used_icb
);
...
...
@@ -248,62 +264,6 @@ static int is_nvcolor(int cspace)
return
0
;
}
/* Allocate memory for the ICBs and mark them as used. */
static
struct
sh_mobile_meram_fb_cache
*
meram_alloc
(
struct
sh_mobile_meram_priv
*
priv
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
int
pixelformat
)
{
struct
sh_mobile_meram_fb_cache
*
cache
;
unsigned
int
nplanes
=
is_nvcolor
(
pixelformat
)
?
2
:
1
;
int
ret
;
if
(
cfg
->
icb
[
0
].
meram_size
==
0
)
return
ERR_PTR
(
-
EINVAL
);
if
(
nplanes
==
2
&&
cfg
->
icb
[
1
].
meram_size
==
0
)
return
ERR_PTR
(
-
EINVAL
);
cache
=
kzalloc
(
sizeof
(
*
cache
),
GFP_KERNEL
);
if
(
cache
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
cache
->
nplanes
=
nplanes
;
ret
=
__meram_alloc
(
priv
,
&
cache
->
planes
[
0
],
cfg
->
icb
[
0
].
meram_size
);
if
(
ret
<
0
)
goto
error
;
cache
->
planes
[
0
].
marker
->
current_reg
=
1
;
cache
->
planes
[
0
].
marker
->
pixelformat
=
pixelformat
;
if
(
cache
->
nplanes
==
1
)
return
cache
;
ret
=
__meram_alloc
(
priv
,
&
cache
->
planes
[
1
],
cfg
->
icb
[
1
].
meram_size
);
if
(
ret
<
0
)
{
__meram_free
(
priv
,
&
cache
->
planes
[
0
]);
goto
error
;
}
return
cache
;
error:
kfree
(
cache
);
return
ERR_PTR
(
-
ENOMEM
);
}
/* Unmark the specified ICB as used. */
static
void
meram_free
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_cache
*
cache
)
{
__meram_free
(
priv
,
&
cache
->
planes
[
0
]);
if
(
cache
->
nplanes
==
2
)
__meram_free
(
priv
,
&
cache
->
planes
[
1
]);
kfree
(
cache
);
}
/* Set the next address to fetch. */
static
void
meram_set_next_addr
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_cache
*
cache
,
...
...
@@ -355,10 +315,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
(((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
/* Initialize MERAM. */
static
int
meram_init
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
*
out_pitch
)
static
int
meram_
plane_
init
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
*
out_pitch
)
{
struct
sh_mobile_meram_icb
*
marker
=
plane
->
marker
;
unsigned
long
total_byte_count
=
MERAM_CALC_BYTECOUNT
(
xres
,
yres
);
...
...
@@ -427,8 +387,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
return
0
;
}
static
void
meram_
deinit
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
)
static
void
meram_
plane_cleanup
(
struct
sh_mobile_meram_priv
*
priv
,
struct
sh_mobile_meram_fb_plane
*
plane
)
{
/* disable ICB */
meram_write_icb
(
priv
->
base
,
plane
->
cache
->
index
,
MExxCTL
,
...
...
@@ -441,20 +401,82 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
}
/* -----------------------------------------------------------------------------
*
Registration/unregistration
*
MERAM operations
*/
static
void
*
sh_mobile_meram_register
(
struct
sh_mobile_meram_info
*
pdata
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
pixelformat
,
unsigned
int
*
pitch
)
unsigned
long
sh_mobile_meram_alloc
(
struct
sh_mobile_meram_info
*
pdata
,
size_t
size
)
{
struct
sh_mobile_meram_priv
*
priv
=
pdata
->
priv
;
return
meram_alloc
(
priv
,
size
);
}
EXPORT_SYMBOL_GPL
(
sh_mobile_meram_alloc
);
void
sh_mobile_meram_free
(
struct
sh_mobile_meram_info
*
pdata
,
unsigned
long
mem
,
size_t
size
)
{
struct
sh_mobile_meram_priv
*
priv
=
pdata
->
priv
;
meram_free
(
priv
,
mem
,
size
);
}
EXPORT_SYMBOL_GPL
(
sh_mobile_meram_free
);
/* Allocate memory for the ICBs and mark them as used. */
static
struct
sh_mobile_meram_fb_cache
*
meram_cache_alloc
(
struct
sh_mobile_meram_priv
*
priv
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
int
pixelformat
)
{
unsigned
int
nplanes
=
is_nvcolor
(
pixelformat
)
?
2
:
1
;
struct
sh_mobile_meram_fb_cache
*
cache
;
int
ret
;
cache
=
kzalloc
(
sizeof
(
*
cache
),
GFP_KERNEL
);
if
(
cache
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
cache
->
nplanes
=
nplanes
;
ret
=
meram_plane_alloc
(
priv
,
&
cache
->
planes
[
0
],
cfg
->
icb
[
0
].
meram_size
);
if
(
ret
<
0
)
goto
error
;
cache
->
planes
[
0
].
marker
->
current_reg
=
1
;
cache
->
planes
[
0
].
marker
->
pixelformat
=
pixelformat
;
if
(
cache
->
nplanes
==
1
)
return
cache
;
ret
=
meram_plane_alloc
(
priv
,
&
cache
->
planes
[
1
],
cfg
->
icb
[
1
].
meram_size
);
if
(
ret
<
0
)
{
meram_plane_free
(
priv
,
&
cache
->
planes
[
0
]);
goto
error
;
}
return
cache
;
error:
kfree
(
cache
);
return
ERR_PTR
(
-
ENOMEM
);
}
void
*
sh_mobile_meram_cache_alloc
(
struct
sh_mobile_meram_info
*
pdata
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
pixelformat
,
unsigned
int
*
pitch
)
{
struct
sh_mobile_meram_fb_cache
*
cache
;
struct
sh_mobile_meram_priv
*
priv
=
pdata
->
priv
;
struct
platform_device
*
pdev
=
pdata
->
pdev
;
unsigned
int
nplanes
=
is_nvcolor
(
pixelformat
)
?
2
:
1
;
unsigned
int
out_pitch
;
if
(
priv
==
NULL
)
return
ERR_PTR
(
-
ENODEV
);
if
(
pixelformat
!=
SH_MOBILE_MERAM_PF_NV
&&
pixelformat
!=
SH_MOBILE_MERAM_PF_NV24
&&
pixelformat
!=
SH_MOBILE_MERAM_PF_RGB
)
...
...
@@ -469,10 +491,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
return
ERR_PTR
(
-
EINVAL
);
}
if
(
cfg
->
icb
[
0
].
meram_size
==
0
)
return
ERR_PTR
(
-
EINVAL
);
if
(
nplanes
==
2
&&
cfg
->
icb
[
1
].
meram_size
==
0
)
return
ERR_PTR
(
-
EINVAL
);
mutex_lock
(
&
priv
->
lock
);
/* We now register the ICBs and allocate the MERAM regions. */
cache
=
meram_alloc
(
priv
,
cfg
,
pixelformat
);
cache
=
meram_
cache_
alloc
(
priv
,
cfg
,
pixelformat
);
if
(
IS_ERR
(
cache
))
{
dev_err
(
&
pdev
->
dev
,
"MERAM allocation failed (%ld)."
,
PTR_ERR
(
cache
));
...
...
@@ -480,42 +508,50 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
}
/* initialize MERAM */
meram_init
(
priv
,
&
cache
->
planes
[
0
],
xres
,
yres
,
&
out_pitch
);
meram_
plane_
init
(
priv
,
&
cache
->
planes
[
0
],
xres
,
yres
,
&
out_pitch
);
*
pitch
=
out_pitch
;
if
(
pixelformat
==
SH_MOBILE_MERAM_PF_NV
)
meram_
init
(
priv
,
&
cache
->
planes
[
1
],
xres
,
(
yres
+
1
)
/
2
,
&
out_pitch
);
meram_
plane_init
(
priv
,
&
cache
->
planes
[
1
]
,
xres
,
(
yres
+
1
)
/
2
,
&
out_pitch
);
else
if
(
pixelformat
==
SH_MOBILE_MERAM_PF_NV24
)
meram_
init
(
priv
,
&
cache
->
planes
[
1
],
2
*
xres
,
(
yres
+
1
)
/
2
,
&
out_pitch
);
meram_
plane_init
(
priv
,
&
cache
->
planes
[
1
]
,
2
*
xres
,
(
yres
+
1
)
/
2
,
&
out_pitch
);
err:
mutex_unlock
(
&
priv
->
lock
);
return
cache
;
}
EXPORT_SYMBOL_GPL
(
sh_mobile_meram_cache_alloc
);
static
void
sh_mobile_meram_
unregister
(
struct
sh_mobile_meram_info
*
pdata
,
void
*
data
)
void
sh_mobile_meram_
cache_free
(
struct
sh_mobile_meram_info
*
pdata
,
void
*
data
)
{
struct
sh_mobile_meram_fb_cache
*
cache
=
data
;
struct
sh_mobile_meram_priv
*
priv
=
pdata
->
priv
;
mutex_lock
(
&
priv
->
lock
);
/* deinit & free */
meram_deinit
(
priv
,
&
cache
->
planes
[
0
]);
if
(
cache
->
nplanes
==
2
)
meram_deinit
(
priv
,
&
cache
->
planes
[
1
]);
/* Cleanup and free. */
meram_plane_cleanup
(
priv
,
&
cache
->
planes
[
0
]);
meram_plane_free
(
priv
,
&
cache
->
planes
[
0
]);
if
(
cache
->
nplanes
==
2
)
{
meram_plane_cleanup
(
priv
,
&
cache
->
planes
[
1
]);
meram_plane_free
(
priv
,
&
cache
->
planes
[
1
]);
}
meram_free
(
priv
,
cache
);
kfree
(
cache
);
mutex_unlock
(
&
priv
->
lock
);
}
static
void
sh_mobile_meram_update
(
struct
sh_mobile_meram_info
*
pdata
,
void
*
data
,
unsigned
long
base_addr_y
,
unsigned
long
base_addr_c
,
unsigned
long
*
icb_addr_y
,
unsigned
long
*
icb_addr_c
)
EXPORT_SYMBOL_GPL
(
sh_mobile_meram_cache_free
);
void
sh_mobile_meram_cache_update
(
struct
sh_mobile_meram_info
*
pdata
,
void
*
data
,
unsigned
long
base_addr_y
,
unsigned
long
base_addr_c
,
unsigned
long
*
icb_addr_y
,
unsigned
long
*
icb_addr_c
)
{
struct
sh_mobile_meram_fb_cache
*
cache
=
data
;
struct
sh_mobile_meram_priv
*
priv
=
pdata
->
priv
;
...
...
@@ -527,13 +563,7 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
mutex_unlock
(
&
priv
->
lock
);
}
static
struct
sh_mobile_meram_ops
sh_mobile_meram_ops
=
{
.
module
=
THIS_MODULE
,
.
meram_register
=
sh_mobile_meram_register
,
.
meram_unregister
=
sh_mobile_meram_unregister
,
.
meram_update
=
sh_mobile_meram_update
,
};
EXPORT_SYMBOL_GPL
(
sh_mobile_meram_cache_update
);
/* -----------------------------------------------------------------------------
* Power management
...
...
@@ -624,7 +654,6 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
for
(
i
=
0
;
i
<
MERAM_ICB_NUM
;
++
i
)
priv
->
icbs
[
i
].
index
=
i
;
pdata
->
ops
=
&
sh_mobile_meram_ops
;
pdata
->
priv
=
priv
;
pdata
->
pdev
=
pdev
;
...
...
include/video/sh_mobile_meram.h
浏览文件 @
4c5b1fb8
...
...
@@ -15,7 +15,6 @@ enum {
struct
sh_mobile_meram_priv
;
struct
sh_mobile_meram_ops
;
/*
* struct sh_mobile_meram_info - MERAM platform data
...
...
@@ -24,7 +23,6 @@ struct sh_mobile_meram_ops;
struct
sh_mobile_meram_info
{
int
addr_mode
;
u32
reserved_icbs
;
struct
sh_mobile_meram_ops
*
ops
;
struct
sh_mobile_meram_priv
*
priv
;
struct
platform_device
*
pdev
;
};
...
...
@@ -38,26 +36,59 @@ struct sh_mobile_meram_cfg {
struct
sh_mobile_meram_icb_cfg
icb
[
2
];
};
struct
module
;
struct
sh_mobile_meram_ops
{
struct
module
*
module
;
/* register usage of meram */
void
*
(
*
meram_register
)(
struct
sh_mobile_meram_info
*
meram_dev
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
pixelformat
,
unsigned
int
*
pitch
);
/* unregister usage of meram */
void
(
*
meram_unregister
)(
struct
sh_mobile_meram_info
*
meram_dev
,
void
*
data
);
/* update meram settings */
void
(
*
meram_update
)(
struct
sh_mobile_meram_info
*
meram_dev
,
void
*
data
,
#if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
unsigned
long
sh_mobile_meram_alloc
(
struct
sh_mobile_meram_info
*
meram_dev
,
size_t
size
);
void
sh_mobile_meram_free
(
struct
sh_mobile_meram_info
*
meram_dev
,
unsigned
long
mem
,
size_t
size
);
void
*
sh_mobile_meram_cache_alloc
(
struct
sh_mobile_meram_info
*
dev
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
pixelformat
,
unsigned
int
*
pitch
);
void
sh_mobile_meram_cache_free
(
struct
sh_mobile_meram_info
*
dev
,
void
*
data
);
void
sh_mobile_meram_cache_update
(
struct
sh_mobile_meram_info
*
dev
,
void
*
data
,
unsigned
long
base_addr_y
,
unsigned
long
base_addr_c
,
unsigned
long
*
icb_addr_y
,
unsigned
long
*
icb_addr_c
);
#else
static
inline
unsigned
long
sh_mobile_meram_alloc
(
struct
sh_mobile_meram_info
*
meram_dev
,
size_t
size
)
{
return
0
;
}
static
inline
void
sh_mobile_meram_free
(
struct
sh_mobile_meram_info
*
meram_dev
,
unsigned
long
mem
,
size_t
size
)
{
}
static
inline
void
*
sh_mobile_meram_cache_alloc
(
struct
sh_mobile_meram_info
*
dev
,
const
struct
sh_mobile_meram_cfg
*
cfg
,
unsigned
int
xres
,
unsigned
int
yres
,
unsigned
int
pixelformat
,
unsigned
int
*
pitch
)
{
return
ERR_PTR
(
-
ENODEV
);
}
static
inline
void
sh_mobile_meram_cache_free
(
struct
sh_mobile_meram_info
*
dev
,
void
*
data
)
{
}
static
inline
void
sh_mobile_meram_cache_update
(
struct
sh_mobile_meram_info
*
dev
,
void
*
data
,
unsigned
long
base_addr_y
,
unsigned
long
base_addr_c
,
unsigned
long
*
icb_addr_y
,
unsigned
long
*
icb_addr_c
);
};
unsigned
long
*
icb_addr_c
)
{
}
#endif
#endif
/* __VIDEO_SH_MOBILE_MERAM_H__ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录