Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4c5b1fb8
Commit
4c5b1fb8
authored
Jul 25, 2012
by
Florian Tobias Schandinat
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-next' of
git://linuxtv.org/pinchartl/fbdev
into fbdev-next
parents
a2c81bc1
a4aa25f6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
293 additions
and
227 deletions
+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
No files found.
drivers/video/sh_mobile_lcdcfb.c
View file @
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
View file @
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
View file @
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
View file @
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__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment