Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
d5c8226e
Commit
d5c8226e
authored
Dec 04, 2009
by
Jean-Paul Saman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Davinci resizer driver
parent
c92b67fa
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
2217 additions
and
0 deletions
+2217
-0
drivers/char/Kconfig
drivers/char/Kconfig
+7
-0
drivers/char/Makefile
drivers/char/Makefile
+3
-0
drivers/char/davinci_resizer.c
drivers/char/davinci_resizer.c
+1659
-0
drivers/char/davinci_resizer.h
drivers/char/davinci_resizer.h
+315
-0
drivers/char/davinci_resizer_hw.c
drivers/char/davinci_resizer_hw.c
+187
-0
drivers/char/davinci_resizer_hw.h
drivers/char/davinci_resizer_hw.h
+46
-0
No files found.
drivers/char/Kconfig
View file @
d5c8226e
...
@@ -1071,6 +1071,13 @@ config HPET_MMAP
...
@@ -1071,6 +1071,13 @@ config HPET_MMAP
exposed to the user. If this applies to your hardware,
exposed to the user. If this applies to your hardware,
say N here.
say N here.
config DAVINCI_RESIZER
tristate "DaVinci Resizer Driver"
default n
depends on ARCH_DAVINCI
help
DaVinci Resizer Driver.
config HANGCHECK_TIMER
config HANGCHECK_TIMER
tristate "Hangcheck timer"
tristate "Hangcheck timer"
depends on X86 || IA64 || PPC64 || S390
depends on X86 || IA64 || PPC64 || S390
...
...
drivers/char/Makefile
View file @
d5c8226e
...
@@ -112,6 +112,9 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
...
@@ -112,6 +112,9 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_JS_RTC)
+=
js-rtc.o
obj-$(CONFIG_JS_RTC)
+=
js-rtc.o
js-rtc-y
=
rtc.o
js-rtc-y
=
rtc.o
davinci_rsz_driver-objs
:=
davinci_resizer_hw.o davinci_resizer.o
obj-$(CONFIG_DAVINCI_RESIZER)
+=
davinci_rsz_driver.o
# Files generated that shall be removed upon make clean
# Files generated that shall be removed upon make clean
clean-files
:=
consolemap_deftbl.c defkeymap.c
clean-files
:=
consolemap_deftbl.c defkeymap.c
...
...
drivers/char/davinci_resizer.c
0 → 100644
View file @
d5c8226e
/* *
* Copyright (C) 2006 Texas Instruments Inc
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not,write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* davinci_resizer.c file */
/* Copyright (c) 2008 Neuros Technology
* ported to udev for 2.6.23. -------- 03-06-2008 mgao@neuros
*
*/
/*Header files*/
#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/slab.h>
/* kmalloc() */
#include <linux/fs.h>
/* everything... */
#include <linux/errno.h>
/* error codes */
#include <linux/types.h>
/* size_t */
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include <linux/err.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#ifdef CONFIG_PREEMPT_RT
#include <linux/completion.h>
#endif
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include "davinci_resizer_hw.h"
#include "davinci_resizer.h"
#define DRIVERNAME "DaVinciResizer"
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"Texas Instruments Davinci video resizer driver"
);
/*Global structute shared between all applications*/
/*struct device_params device_config;*/
device_params_t
device_config
;
/* For registeration of charatcer device*/
static
struct
cdev
c_dev
;
/* device structure to make entry in device*/
static
dev_t
dev
;
/* for holding device entry*/
struct
device
*
rsz_device
=
NULL
;
/*
* functions definition
*/
extern
void
rsz_hardware_setup
(
channel_config_t
*
rsz_conf_chan
);
extern
int
rsz_enable
(
channel_config_t
*
rsz_conf_chan
);
extern
int
rsz_writebuffer_status
(
void
);
/* Local Functions Definition
*/
static
int
malloc_buff
(
rsz_reqbufs_t
*
,
channel_config_t
*
);
static
int
get_buf_address
(
rsz_buffer_t
*
,
channel_config_t
*
);
static
int
rsz_start
(
rsz_resize_t
*
,
channel_config_t
*
);
static
int
add_to_array
(
channel_config_t
*
rsz_configuration_channel
);
static
int
delete_from_array
(
channel_config_t
*
rsz_configuration_channel
);
static
int
rsz_set_params
(
rsz_params_t
*
,
channel_config_t
*
);
static
int
rsz_get_params
(
rsz_params_t
*
,
channel_config_t
*
);
static
int
free_buff
(
channel_config_t
*
rsz_configuration_channel
);
static
irqreturn_t
rsz_isr
(
int
,
void
*
);
static
void
rsz_calculate_crop
(
channel_config_t
*
rsz_conf_chan
,
rsz_cropsize_t
*
cropsize
);
static
void
inline
rsz_set_exp
(
int
exp
)
{
regw
(((
exp
&
0x3ff
)
<<
10
),
SDR_REQ_EXP
);
}
/* inline function to free reserver pages */
static
void
inline
rsz_free_pages
(
unsigned
long
addr
,
unsigned
long
bufsize
)
{
unsigned
long
size
;
unsigned
long
tempaddr
;
tempaddr
=
addr
;
if
(
!
addr
)
return
;
size
=
PAGE_SIZE
<<
(
get_order
(
bufsize
));
while
(
size
>
0
)
{
ClearPageReserved
(
virt_to_page
(
addr
));
addr
+=
PAGE_SIZE
;
size
-=
PAGE_SIZE
;
}
free_pages
(
tempaddr
,
get_order
(
bufsize
));
}
/*
=====================malloc_buff===========================
Function to allocate memory to input and output buffers
*/
static
int
malloc_buff
(
rsz_reqbufs_t
*
reqbuff
,
channel_config_t
*
rsz_conf_chan
)
{
/* For looping purpose */
int
buf_index
=
ZERO
;
/* For calculating the difference between new buffers to be allocated */
int
diff
;
/* for pointing to input or output buffer pointer */
int
*
buf_ptr
,
*
buf_start
;
/* To calculate no of max buffers; */
int
maxbuffers
;
/* to calculate number of buffers allocated */
unsigned
int
numbuffers
=
ZERO
;
/* for storing buffer size */
int
*
buf_size
;
/* to free the number of allocared buffers */
int
free_index
;
/* to make sure buffer pointer never swapped */
unsigned
long
adr
;
unsigned
long
size
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* assigning the buf_ptr to input buffer which is array of void
pointer */
if
(
reqbuff
->
buf_type
==
RSZ_BUF_IN
)
{
dev_dbg
(
rsz_device
,
"Input buffer requested
\n
"
);
buf_ptr
=
(
int
*
)
rsz_conf_chan
->
input_buffer
;
buf_size
=
&
rsz_conf_chan
->
in_bufsize
;
maxbuffers
=
MAX_INPUT_BUFFERS
;
}
/* assigning the buf_ptr to output buffer which is array of
void pointer */
else
if
(
reqbuff
->
buf_type
==
RSZ_BUF_OUT
)
{
dev_dbg
(
rsz_device
,
"Output buffer requested
\n
"
);
buf_ptr
=
(
int
*
)
rsz_conf_chan
->
output_buffer
;
buf_size
=
&
rsz_conf_chan
->
out_bufsize
;
maxbuffers
=
MAX_OUTPUT_BUFFERS
;
}
else
{
dev_dbg
(
rsz_device
,
"Invalid type
\n
"
);
return
-
EINVAL
;
}
/* Check the request for number of buffers */
if
(
reqbuff
->
count
>
maxbuffers
)
return
-
EINVAL
;
/* Counting the number of buffers allocated */
dev_dbg
(
rsz_device
,
"The requested size of buffer is %d
\n
"
,
reqbuff
->
size
);
buf_start
=
buf_ptr
;
while
(
*
(
buf_ptr
)
!=
(
int
)
NULL
&&
numbuffers
<
maxbuffers
)
{
numbuffers
++
;
buf_ptr
++
;
}
buf_ptr
=
buf_start
;
/* Free all the buffers if the count is zero */
if
(
reqbuff
->
count
==
FREE_BUFFER
)
{
/* Free all the buffers */
for
(
buf_index
=
ZERO
;
buf_index
<
numbuffers
;
buf_index
++
)
{
/* free memory allocate for the image */
dev_dbg
(
rsz_device
,
"Free all the allocated buffers
\n
"
);
/* Free buffers using free_pages */
rsz_free_pages
(
*
buf_ptr
,
*
buf_size
);
/* assign buffer zero to indicate its free */
*
buf_ptr
=
(
int
)
NULL
;
buf_ptr
++
;
}
return
SUCESS
;
}
/* If buffers are previously allocated, size has to be same */
if
(
numbuffers
)
{
if
(
reqbuff
->
size
!=
*
buf_size
)
{
for
(
buf_index
=
ZERO
;
buf_index
<
numbuffers
;
buf_index
++
)
{
/* free memory allocate for the image */
/* Free buffers using free_pages */
rsz_free_pages
(
*
buf_ptr
,
*
buf_size
);
/* assign buffer zero to indicate its free */
*
buf_ptr
=
(
int
)
NULL
;
buf_ptr
++
;
}
numbuffers
=
ZERO
;
buf_ptr
=
buf_start
;
}
}
/* get the difference to know how mnay buffers to allocate */
dev_dbg
(
rsz_device
,
"The no of requested buffers are %d
\n
"
,
reqbuff
->
count
);
diff
=
numbuffers
-
reqbuff
->
count
;
if
(
diff
>
ZERO
)
{
buf_ptr
=
buf_ptr
+
reqbuff
->
count
;
for
(
buf_index
=
reqbuff
->
count
;
buf_index
<
numbuffers
;
buf_index
++
)
{
/* if difference is positive than deallocate that
much memory of input buff */
/* free buffer using free_pages */
rsz_free_pages
(
*
buf_ptr
,
*
buf_size
);
/* assign buffer zero to indicate its free */
*
buf_ptr
=
(
int
)
NULL
;
buf_ptr
++
;
}
}
else
{
/* make the difference positive */
diff
=
reqbuff
->
count
-
numbuffers
;
buf_ptr
=
buf_ptr
+
numbuffers
;
for
(
buf_index
=
numbuffers
;
buf_index
<
reqbuff
->
count
;
buf_index
++
)
{
/* assign memory to buffer */
*
buf_ptr
=
(
int
)(
__get_free_pages
(
GFP_KERNEL
|
GFP_DMA
,
get_order
(
reqbuff
->
size
)));
if
(
!
(
*
buf_ptr
))
{
buf_ptr
=
(
buf_ptr
-
(
buf_index
-
numbuffers
));
for
(
free_index
=
numbuffers
;
free_index
<
buf_index
;
free_index
++
)
{
rsz_free_pages
(
*
buf_ptr
,
*
buf_size
);
buf_ptr
++
;
}
dev_dbg
(
rsz_device
,
"requestbuffer:not enough memory"
);
return
-
ENOMEM
;
}
adr
=
*
buf_ptr
;
size
=
PAGE_SIZE
<<
(
get_order
(
reqbuff
->
size
));
while
(
size
>
0
)
{
/* make sure the frame buffers
are never swapped out of memory */
SetPageReserved
(
virt_to_page
(
adr
));
adr
+=
PAGE_SIZE
;
size
-=
PAGE_SIZE
;
}
buf_ptr
++
;
}
}
/* set the buffer size to requested size */
/* this will be useful only when numbuffers = 0 */
*
buf_size
=
reqbuff
->
size
;
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/* end of function Main_buff */
/*====================get_buf_address===========================*/
/* Function to query the physical address of the buffer requested by index*/
static
int
get_buf_address
(
rsz_buffer_t
*
buffer
,
channel_config_t
*
rsz_conf_chan
)
{
int
buffer_index
=
0
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
if
(
buffer
==
NULL
)
return
-
EINVAL
;
if
(
buffer
->
buf_type
==
RSZ_BUF_IN
)
{
/* Check the request for number of input buffers */
if
(
buffer
->
index
>
MAX_INPUT_BUFFERS
)
return
-
EINVAL
;
/*count number of input buffer allocated */
while
((
rsz_conf_chan
->
input_buffer
[
buffer_index
]
!=
NULL
)
&&
(
buffer_index
<
MAX_INPUT_BUFFERS
))
{
buffer_index
++
;
}
/*checking the index requested */
if
(
buffer
->
index
>=
buffer_index
)
{
dev_dbg
(
rsz_device
,
"Requested buffer not allocated
\n
"
);
return
-
EINVAL
;
}
/* assignning the input address to offset which will be
used in mmap */
buffer
->
offset
=
((
int
)(
rsz_conf_chan
->
input_buffer
[
buffer
->
index
]));
dev_dbg
(
rsz_device
,
"The query input offset is %x"
,
buffer
->
offset
);
}
else
if
(
buffer
->
buf_type
==
RSZ_BUF_OUT
)
{
/* Check the request for number of output buffers */
if
(
buffer
->
index
>
MAX_OUTPUT_BUFFERS
)
return
-
EINVAL
;
/* counting number of output buffers */
while
((
rsz_conf_chan
->
output_buffer
[
buffer_index
]
!=
NULL
)
&&
(
buffer_index
<
MAX_OUTPUT_BUFFERS
))
{
buffer_index
++
;
}
/* checking the index requested */
if
(
buffer
->
index
>=
buffer_index
)
{
dev_dbg
(
rsz_device
,
"Requested buffer not allocated
\n
"
);
return
-
EINVAL
;
}
/* assignning the output address to offset which will be
used in mmap */
buffer
->
offset
=
((
int
)(
rsz_conf_chan
->
output_buffer
[
buffer
->
index
]));
dev_dbg
(
rsz_device
,
"The query output offset is %x"
,
buffer
->
offset
);
}
else
{
dev_dbg
(
rsz_device
,
" Invalid input type
\n
"
);
return
-
EINVAL
;
}
/* look up physical address of the buffer */
buffer
->
offset
=
virt_to_phys
((
void
*
)
buffer
->
offset
);
dev_dbg
(
rsz_device
,
"the physical offset returned after query \
is %x"
,
buffer
->
offset
);
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/*End of function getBufferAddress */
/*
=====================rsz_start===========================
This function enable the resize bit after doing the hardware register
configuration after which resizing will be carried on.
*/
static
int
rsz_start
(
rsz_resize_t
*
resize
,
channel_config_t
*
rsz_conf_chan
)
{
/* Holds the input address to the resizer */
int
in_address
;
/* Holds the output address to resizer */
int
out_address
;
/* Conatains the input put and output buffer allocated size */
int
out_bufsize
,
in_bufsize
;
/* Conatins the pitch and vertical size of input and output image */
int
in_vsize
,
in_pitch
,
out_vsize
,
out_pitch
;
/* holds the return value; */
int
ret
;
/* For calculating the number of input buffers allocated */
int
buffer_in_index
=
ZERO
;
/* For calculating the number of output buffers allocated */
int
buffer_out_index
=
ZERO
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* checking the configuartion status */
if
(
rsz_conf_chan
->
config_state
)
{
dev_dbg
(
rsz_device
,
"State not configured
\n
"
);
return
-
EINVAL
;
}
/* Taking the inpitch of the image */
in_pitch
=
rsz_conf_chan
->
register_config
.
rsz_sdr_inoff
&
~
(
RSZ_SDR_INOFF_OFFSET_MASK
);
/* Taking the out pitch of image */
in_vsize
=
((
rsz_conf_chan
->
register_config
.
rsz_in_size
&
~
(
RSZ_IN_SIZE_VERT_MASK
))
>>
RSZ_IN_SIZE_VERT_SHIFT
);
in_bufsize
=
in_vsize
*
in_pitch
;
/*getting the outpitch */
out_pitch
=
rsz_conf_chan
->
register_config
.
rsz_sdr_outoff
&
~
(
RSZ_SDR_OUTOFF_OFFSET_MASK
);
/* getting the vertical size */
out_vsize
=
((
rsz_conf_chan
->
register_config
.
rsz_out_size
&
~
(
RSZ_OUT_SIZE_VERT_MASK
))
>>
RSZ_OUT_VSIZE_SHIFT
);
out_bufsize
=
out_vsize
*
out_pitch
;
if
(
resize
->
in_buf
.
index
<
ZERO
)
{
/* assignning the address to the register configuration */
if
(
resize
->
in_buf
.
size
>=
in_bufsize
)
{
if
(
resize
->
in_buf
.
offset
%
32
)
return
-
EINVAL
;
rsz_conf_chan
->
register_config
.
rsz_sdr_inadd
=
resize
->
in_buf
.
offset
;
}
else
{
dev_err
(
rsz_device
,
" invalid size
\n
"
);
return
-
EINVAL
;
}
}
else
{
if
(
resize
->
in_buf
.
index
>
MAX_INPUT_BUFFERS
)
return
-
EINVAL
;
/*count number of input buffer allocated */
while
((
rsz_conf_chan
->
input_buffer
[
buffer_in_index
]
!=
NULL
)
&&
(
buffer_in_index
<
MAX_INPUT_BUFFERS
))
{
buffer_in_index
++
;
}
/*checking the index requested */
if
(
resize
->
in_buf
.
index
>=
buffer_in_index
)
{
dev_dbg
(
rsz_device
,
"Requested buffer not allocated
\n
"
);
return
-
EINVAL
;
}
in_address
=
virt_to_phys
(((
void
*
)
rsz_conf_chan
->
input_buffer
[
resize
->
in_buf
.
index
]));
rsz_conf_chan
->
register_config
.
rsz_sdr_inadd
=
in_address
;
}
if
(
resize
->
out_buf
.
index
<
ZERO
)
{
if
(
resize
->
out_buf
.
size
>=
out_bufsize
)
{
if
(
resize
->
out_buf
.
offset
%
32
)
return
-
EINVAL
;
rsz_conf_chan
->
register_config
.
rsz_sdr_outadd
=
resize
->
out_buf
.
offset
;
}
else
{
dev_err
(
rsz_device
,
"Invalid output size
\n
"
);
return
-
EINVAL
;
}
}
else
{
if
(
resize
->
out_buf
.
index
>
MAX_OUTPUT_BUFFERS
)
return
-
EINVAL
;
/*count number of input buffer allocated */
while
((
rsz_conf_chan
->
output_buffer
[
buffer_out_index
]
!=
NULL
)
&&
(
buffer_out_index
<
MAX_OUTPUT_BUFFERS
))
{
buffer_out_index
++
;
}
/*checking the index requested */
if
(
resize
->
out_buf
.
index
>=
buffer_out_index
)
{
dev_dbg
(
rsz_device
,
"Requested buffer not allocated
\n
"
);
return
-
EINVAL
;
}
out_address
=
virt_to_phys
(((
void
*
)
(
rsz_conf_chan
->
output_buffer
[
resize
->
out_buf
.
index
])));
rsz_conf_chan
->
register_config
.
rsz_sdr_outadd
=
out_address
;
}
/* Channel is busy */
dev_dbg
(
rsz_device
,
"
\n
The physical add in rsz start is %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_sdr_inadd
);
rsz_conf_chan
->
status
=
CHANNEL_BUSY
;
/* Function call to add the entry of application in array */
ret
=
add_to_array
(
rsz_conf_chan
);
/*Function call to set up the hardware */
rsz_hardware_setup
(
rsz_conf_chan
);
dev_dbg
(
rsz_device
,
"After Hardware Setup PCR = %x"
,
regr
(
PCR
));
/* Initialize the interrupt ISR to ZER0 */
device_config
.
sem_isr
.
done
=
ZERO
;
/*Function call to enable resizer hardware */
ret
=
rsz_enable
(
rsz_conf_chan
);
dev_dbg
(
rsz_device
,
"After ENABLE PCR = %x"
,
regr
(
PCR
));
/* Waiting for resizing to be complete */
wait_for_completion_interruptible
(
&
(
device_config
.
sem_isr
));
rsz_conf_chan
->
status
=
CHANNEL_FREE
;
if
(
rsz_writebuffer_status
()
!=
0
)
{
dev_err
(
rsz_device
,
"Error: Resizer write buffer overflow:
\n
"
);
}
delete_from_array
(
rsz_conf_chan
);
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
ret
;
}
/*End of function Start_Resize */
/*
=====================add_to_array===========================
Function to add the current channel configuration into array
according to priority.
*/
static
int
add_to_array
(
channel_config_t
*
rsz_conf_chan
)
{
int
array_index
,
device_index
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* locking the configuartion aaray */
down_interruptible
(
&
device_config
.
array_sem
);
/* Add configuration to the queue according to its priority */
if
(
device_config
.
array_count
==
EMPTY
)
{
/* If array empty insert at top position */
dev_dbg
(
rsz_device
,
"First request for resizing
\n
"
);
device_config
.
channel_configuration
[
device_config
.
array_count
]
=
rsz_conf_chan
;
}
else
{
/* Check the priority and insert according to the priority */
/* it will start from first index */
for
(
array_index
=
SECONDENTRY
;
array_index
<
device_config
.
array_count
;
array_index
++
)
{
if
(
device_config
.
channel_configuration
[
array_index
]
->
priority
<
rsz_conf_chan
->
priority
)
break
;
}
/* Shift all the elements one step down in array */
/* IF firstelement and second have same prioroty than insert */
/* below first */
for
(
device_index
=
device_config
.
array_count
;
device_index
>
array_index
;
device_index
--
)
{
device_config
.
channel_configuration
[
device_index
]
=
device_config
.
channel_configuration
[
device_index
-
NEXT
];
}
device_config
.
channel_configuration
[
array_index
]
=
rsz_conf_chan
;
}
/* incrementing number of requests for resizing */
device_config
.
array_count
++
;
dev_dbg
(
rsz_device
,
"The total request for resizing are %d"
,
device_config
.
array_count
);
if
(
device_config
.
array_count
!=
SECONDENTRY
)
{
up
(
&
device_config
.
array_sem
);
/* if the request is pending that lock the request */
#ifdef CONFIG_PREEMPT_RT
wait_for_completion_interruptible
(
&
(
rsz_conf_chan
->
channel_sem
));
#else
down_interruptible
(
&
(
rsz_conf_chan
->
channel_sem
));
#endif
}
else
{
up
(
&
device_config
.
array_sem
);
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/* end of function addToarray */
/*
=====================delete_from_array===========================
Function to delete the processed array entry form the array
*/
static
int
delete_from_array
(
channel_config_t
*
rsz_conf_chan
)
{
int
array_index
=
FIRSTENTRY
,
device_index
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
down_interruptible
(
&
(
device_config
.
array_sem
));
/*shift the entried in array */
if
(
device_config
.
array_count
!=
SECONDENTRY
)
{
/* decrementing the request count */
device_config
.
array_count
--
;
/* Shift all the elements one step up in array */
for
(
device_index
=
array_index
;
device_index
<
device_config
.
array_count
;
device_index
++
)
{
device_config
.
channel_configuration
[
device_index
]
=
device_config
.
channel_configuration
[
device_index
+
NEXT
];
}
/* making last entry NULL; */
device_config
.
channel_configuration
[
device_index
+
NEXT
]
=
NULL
;
}
/* remove the top entry */
else
{
dev_dbg
(
rsz_device
,
"
\n
Removing the first request"
);
device_config
.
array_count
--
;
device_config
.
channel_configuration
[
FIRSTENTRY
]
=
NULL
;
}
if
(
device_config
.
array_count
!=
FIRSTENTRY
)
{
/* Get config having highest priority in array
resizer_device.config
and unlock config.sem of that config */
dev_dbg
(
rsz_device
,
"Releasing array lock of the second entry
\n
"
);
#ifdef CONFIG_PREEMPT_RT
complete
(
&
(
device_config
.
channel_configuration
[
FIRSTENTRY
]
->
channel_sem
));
#else
up
(
&
(
device_config
.
channel_configuration
[
FIRSTENTRY
]
->
channel_sem
));
#endif
up
(
&
(
device_config
.
array_sem
));
}
else
{
dev_dbg
(
rsz_device
,
"Releasing array lock
\n
"
);
up
(
&
(
device_config
.
array_sem
));
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/* end of function deleteFromarray */
static
int
rsz_set_params
(
rsz_params_t
*
params
,
channel_config_t
*
rsz_conf_chan
)
{
int
coeffcounter
;
int
hrsz
=
ZERO
;
int
vrsz
=
ZERO
;
int
alignment
=
ZERO
;
int
hsize
;
int
vsize
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* calculating the horizontal and vertical ratio */
vrsz
=
(
params
->
in_vsize
-
NUM_D2TAPS
)
*
RATIO_MULTIPLIER
/
(
params
->
out_vsize
-
1
);
hrsz
=
((
params
->
in_hsize
-
NUM_D2TAPS
)
*
RATIO_MULTIPLIER
)
/
(
params
->
out_hsize
-
1
);
/* recalculating Horizontal ratio */
if
(
hrsz
<=
DOWN_RSZ_RATIO
)
{
/* 4-tap 8-phase filter */
hrsz
=
(
params
->
in_hsize
-
NUM_TAPS
)
*
RATIO_MULTIPLIER
/
(
params
->
out_hsize
-
1
);
if
(
hrsz
>
DOWN_RSZ_RATIO
)
hrsz
=
DOWN_RSZ_RATIO
;
if
(
params
->
hstph
>
NUM_PHASES
)
return
-
EINVAL
;
}
else
if
(
hrsz
>=
UP_RSZ_RATIO1
&&
hrsz
<=
DOWN_RSZ_RATIO1
)
{
/* 7-tap 4-phase filter */
if
(
params
->
hstph
>
NUM_D2PH
)
return
-
EINVAL
;
}
/* recalculating vertical ratio */
if
(
vrsz
<=
DOWN_RSZ_RATIO
)
{
/* 4-tap 8-phase filter */
vrsz
=
(
params
->
in_vsize
-
NUM_TAPS
)
*
RATIO_MULTIPLIER
/
(
params
->
out_vsize
-
1
);
if
(
vrsz
>
DOWN_RSZ_RATIO
)
vrsz
=
DOWN_RSZ_RATIO
;
if
(
params
->
vstph
>
NUM_PHASES
)
return
-
EINVAL
;
}
else
if
(
vrsz
>=
UP_RSZ_RATIO1
&&
vrsz
<=
DOWN_RSZ_RATIO1
)
{
if
(
params
->
vstph
>
NUM_D2PH
)
return
-
EINVAL
;
}
/* Fiiling the input pitch in the structure */
if
((
params
->
in_pitch
)
%
ALIGN32
)
{
dev_err
(
rsz_device
,
"Inavlid input pitch %d
\n
"
,
params
->
in_pitch
);
return
-
EINVAL
;
}
rsz_conf_chan
->
register_config
.
rsz_sdr_inoff
=
((
params
->
in_pitch
)
&
~
(
RSZ_SDR_INOFF_OFFSET_MASK
));
/* If vertical upsizing then */
if
(
vrsz
<
256
)
{
/* checking for both types of format */
if
(
params
->
inptyp
==
RSZ_INTYPE_PLANAR_8BIT
)
{
alignment
=
ALIGNMENT
;
}
else
if
(
params
->
inptyp
==
RSZ_INTYPE_YCBCR422_16BIT
)
{
alignment
=
(
ALIGNMENT
/
2
);
}
else
{
dev_err
(
rsz_device
,
"Invalid input type
\n
"
);
}
/* errror checking for output size */
if
(
!
(((
params
->
out_hsize
%
PIXEL_EVEN
)
==
ZERO
)
&&
(
params
->
out_hsize
%
alignment
)
==
ZERO
))
{
dev_err
(
rsz_device
,
"wrong hsize
\n
"
);
return
-
EINVAL
;
}
}
if
(
hrsz
>=
UP_RSZ_RATIO
&&
hrsz
<=
DOWN_RSZ_RATIO
)
{
if
(
params
->
out_hsize
>
MAX_IMAGE_WIDTH
)
{
dev_err
(
rsz_device
,
"wrong width
\n
"
);
return
-
EINVAL
;
}
}
else
if
(
hrsz
>=
UP_RSZ_RATIO1
&&
hrsz
<=
DOWN_RSZ_RATIO1
)
{
if
(
params
->
out_hsize
>
MAX_IMAGE_WIDTH_HIGH
)
{
dev_err
(
rsz_device
,
"wrong width
\n
"
);
return
-
EINVAL
;
}
}
else
{
dev_err
(
rsz_device
,
"horizontal scaling ratio invalid: %d, %d, %dn"
,
hrsz
,
params
->
in_hsize
,
params
->
out_hsize
);
return
-
EINVAL
;
}
if
(
vrsz
<
UP_RSZ_RATIO
||
vrsz
>
DOWN_RSZ_RATIO1
)
{
dev_err
(
rsz_device
,
"vertical scaling ratio invalid:%d,%d,%d
\n
"
,
vrsz
,
params
->
in_vsize
,
params
->
out_vsize
);
return
-
EINVAL
;
}
rsz_conf_chan
->
register_config
.
rsz_out_size
=
(
params
->
out_hsize
&
~
(
RSZ_OUT_SIZE_HORZ_MASK
));
rsz_conf_chan
->
register_config
.
rsz_out_size
|=
((
params
->
out_vsize
<<
RSZ_OUT_VSIZE_SHIFT
)
&
~
(
RSZ_OUT_SIZE_VERT_MASK
));
dev_dbg
(
rsz_device
,
"The outpitch in driver is %d"
,
params
->
out_pitch
);
if
((
params
->
out_pitch
)
%
ALIGN32
)
{
dev_err
(
rsz_device
,
"Inavlid output pitch
\n
"
);
return
-
EINVAL
;
}
rsz_conf_chan
->
register_config
.
rsz_sdr_outoff
=
params
->
out_pitch
&
~
(
RSZ_SDR_OUTOFF_OFFSET_MASK
);
rsz_conf_chan
->
register_config
.
rsz_cnt
=
0
;
/* clear the rsz_cnt register */
/* Configuring the chrominance algorithm */
if
(
params
->
cbilin
)
{
rsz_conf_chan
->
register_config
.
rsz_cnt
=
BITSET
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
SET_BIT_CBLIN
);
dev_dbg
(
rsz_device
,
"Setting chrominance algorithm bit
\n
"
);
}
/* Configuring the input source */
if
(
INPUT_RAM
)
{
dev_dbg
(
rsz_device
,
"Setting Input source as Ram
\n
"
);
rsz_conf_chan
->
register_config
.
rsz_cnt
=
BITSET
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
SET_BIT_INPUTRAM
);
}
/* Configuring the input type */
if
(
params
->
inptyp
==
RSZ_INTYPE_PLANAR_8BIT
)
{
dev_dbg
(
rsz_device
,
"Setting pic format as 8 bit planar
\n
"
);
rsz_conf_chan
->
register_config
.
rsz_cnt
=
BITSET
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
SET_BIT_INPTYP
);
}
else
{
dev_dbg
(
rsz_device
,
"Setting pic format as 16 bit color seperated
\n
"
);
rsz_conf_chan
->
register_config
.
rsz_cnt
=
BITRESET
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
SET_BIT_INPTYP
);
/* Configuring the chrominace position type */
if
(
params
->
pix_fmt
==
RSZ_PIX_FMT_UYVY
)
{
rsz_conf_chan
->
register_config
.
rsz_cnt
=
BITSET
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
SET_BIT_YCPOS
);
}
else
if
(
params
->
pix_fmt
==
RSZ_PIX_FMT_YUYV
)
{
rsz_conf_chan
->
register_config
.
rsz_cnt
=
BITRESET
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
SET_BIT_YCPOS
);
}
}
/* checking the validity of the horizontal phase value */
if
(
hrsz
>=
UP_RSZ_RATIO
&&
hrsz
<=
DOWN_RSZ_RATIO
)
{
if
(
params
->
hstph
>
NUM_PHASES
)
return
-
EINVAL
;
}
else
if
(
hrsz
>=
UP_RSZ_RATIO
&&
hrsz
<=
DOWN_RSZ_RATIO
)
{
if
(
params
->
hstph
>
NUM_D2PH
)
return
-
EINVAL
;
}
rsz_conf_chan
->
register_config
.
rsz_cnt
|=
((
params
->
hstph
<<
RSZ_HSTP_SHIFT
)
&
~
(
RSZ_HSTPH_MASK
));
/* checking the validity of the vertical phase value */
if
(
vrsz
>=
UP_RSZ_RATIO
&&
hrsz
<=
DOWN_RSZ_RATIO
)
{
if
(
params
->
vstph
>
NUM_PHASES
)
return
-
EINVAL
;
}
else
if
(
vrsz
>=
UP_RSZ_RATIO
&&
vrsz
<=
DOWN_RSZ_RATIO
)
{
if
(
params
->
vstph
>
NUM_D2PH
)
return
-
EINVAL
;
}
rsz_conf_chan
->
register_config
.
rsz_cnt
|=
((
params
->
vstph
<<
RSZ_VSTPH_SHIFT
)
&
~
(
RSZ_VSTPH_MASK
));
/* if input is from ram that vertical pixel should be zero */
if
(
INPUT_RAM
)
{
params
->
vert_starting_pixel
=
ZERO
;
}
/* Configuring the starting pixel in vertical direction */
rsz_conf_chan
->
register_config
.
rsz_in_start
=
(
params
->
vert_starting_pixel
<<
RSZ_IN_SIZE_VERT_SHIFT
)
&
~
(
RSZ_IN_START_VERT_ST_MASK
);
/* if input is 8 bit that start pixel should be <= to than 31 */
if
(
params
->
inptyp
==
RSZ_INTYPE_PLANAR_8BIT
)
{
if
(
params
->
horz_starting_pixel
>
MAX_HORZ_PIXEL_8BIT
)
return
-
EINVAL
;
}
/* if input is 16 bit that start pixel should be <= than 15 */
if
(
params
->
inptyp
==
RSZ_INTYPE_YCBCR422_16BIT
)
{
if
(
params
->
horz_starting_pixel
>
MAX_HORZ_PIXEL_16BIT
)
return
-
EINVAL
;
}
/* Configuring the starting pixel in horizontal direction */
rsz_conf_chan
->
register_config
.
rsz_in_start
|=
params
->
horz_starting_pixel
&
~
(
RSZ_IN_START_HORZ_ST_MASK
);
for
(
coeffcounter
=
ZERO
;
coeffcounter
<
MAX_COEF_COUNTER
;
coeffcounter
++
)
{
/* Configuration of horizontal coefficients */
rsz_conf_chan
->
register_config
.
rsz_coeff_horz
[
coeffcounter
]
=
(
params
->
hfilt_coeffs
[
2
*
coeffcounter
]
&
~
(
RSZ_FILTER_COEFF0_MASK
));
/* Configuration of horizontal coefficients */
rsz_conf_chan
->
register_config
.
rsz_coeff_horz
[
coeffcounter
]
|=
((
params
->
hfilt_coeffs
[
2
*
coeffcounter
+
NEXT
]
<<
RSZ_FILTER_COEFF_SHIFT
)
&
~
(
RSZ_FILTER_COEFF1_MASK
));
/* Configuration of Vertical coefficients */
rsz_conf_chan
->
register_config
.
rsz_coeff_vert
[
coeffcounter
]
=
(
params
->
vfilt_coeffs
[
2
*
coeffcounter
]
&
~
(
RSZ_FILTER_COEFF0_MASK
));
/* Configuration of Vertical coefficients */
rsz_conf_chan
->
register_config
.
rsz_coeff_vert
[
coeffcounter
]
|=
((
params
->
vfilt_coeffs
[
2
*
coeffcounter
+
NEXT
]
<<
RSZ_FILTER_COEFF_SHIFT
)
&
~
(
RSZ_FILTER_COEFF1_MASK
));
}
/* Coefficinets of parameters for luma :- algo configuration */
rsz_conf_chan
->
register_config
.
rsz_yehn
=
((
params
->
yenh_params
.
type
<<
RSZ_YENH_TYPE_SHIFT
)
&
~
(
RSZ_YEHN_ALGO_MASK
));
/* Coefficinets of parameters for luma :- core configuration */
if
(
params
->
yenh_params
.
type
)
{
rsz_conf_chan
->
register_config
.
rsz_yehn
|=
params
->
yenh_params
.
core
&
~
(
RSZ_YEHN_CORE_MASK
);
/* Coefficinets of parameters for luma :- gain configuration */
rsz_conf_chan
->
register_config
.
rsz_yehn
|=
((
params
->
yenh_params
.
gain
<<
RSZ_YENH_GAIN_SHIFT
)
&
~
(
RSZ_YEHN_GAIN_MASK
));
/* Coefficinets of parameters for luma :- gain configuration */
rsz_conf_chan
->
register_config
.
rsz_yehn
|=
((
params
->
yenh_params
.
slop
<<
RSZ_YENH_SLOP_SHIFT
)
&
~
(
RSZ_YEHN_SLOP_MASK
));
}
/* Configuring the horizonatl ratio */
rsz_conf_chan
->
register_config
.
rsz_cnt
|=
((
hrsz
-
1
)
&
~
RSZ_HRSZ_MASK
);
/* Configuring the vertical ratio */
rsz_conf_chan
->
register_config
.
rsz_cnt
|=
(((
vrsz
-
1
)
<<
RSZ_VRSZ_SHIFT
)
&
~
RSZ_VRSZ_MASK
);
if
(
hrsz
<=
512
)
{
/*4-tap filter */
hsize
=
((
32
*
params
->
hstph
+
(
params
->
out_hsize
-
1
)
*
hrsz
+
16
)
>>
8
)
+
7
;
}
else
{
hsize
=
((
64
*
params
->
hstph
+
(
params
->
out_hsize
-
1
)
*
hrsz
+
32
)
>>
8
)
+
7
;
}
dev_dbg
(
rsz_device
,
"hsize = %d
\n
"
,
hsize
);
if
(
vrsz
<=
512
)
{
/*4-tap filter */
vsize
=
((
32
*
params
->
vstph
+
(
params
->
out_vsize
-
1
)
*
vrsz
+
16
)
>>
8
)
+
4
;
}
else
{
vsize
=
((
64
*
params
->
vstph
+
(
params
->
out_vsize
-
1
)
*
vrsz
+
32
)
>>
8
)
+
7
;
}
dev_dbg
(
rsz_device
,
"vsize = %d
\n
"
,
vsize
);
dev_dbg
(
rsz_device
,
"hrsz = %d, vrsz = %d,
\n
"
,
hrsz
,
vrsz
);
/* Configuring the Horizontal size of inputframn in MMR */
rsz_conf_chan
->
register_config
.
rsz_in_size
=
hsize
;
/*params->in_hsize; */
rsz_conf_chan
->
register_config
.
rsz_in_size
|=
((
vsize
/*params->in_vsize */
<<
RSZ_IN_SIZE_VERT_SHIFT
)
&
~
(
RSZ_IN_SIZE_VERT_MASK
));
/*Setting the configuration status */
dev_dbg
(
rsz_device
,
"Resizer State configured
\n
"
);
rsz_conf_chan
->
config_state
=
STATE_CONFIGURED
;
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/*End of rsz_Set_Params */
/* End of rsz_Set_Params*/
/*
=====================rsz_Get_Params===========================
Function to get the parameters values
*/
static
int
rsz_get_params
(
rsz_params_t
*
params
,
channel_config_t
*
rsz_conf_chan
)
{
int
coeffcounter
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
if
(
rsz_conf_chan
->
config_state
)
{
dev_dbg
(
rsz_device
,
" state not configured
\n
"
);
return
-
EINVAL
;
}
/* getting the horizontal size */
params
->
in_hsize
=
rsz_conf_chan
->
register_config
.
rsz_in_size
&
~
(
RSZ_IN_SIZE_HORZ_MASK
);
/* getting the vertical size */
params
->
in_vsize
=
((
rsz_conf_chan
->
register_config
.
rsz_in_size
&
~
(
RSZ_IN_SIZE_VERT_MASK
))
>>
RSZ_IN_SIZE_VERT_SHIFT
);
/* getting the input pitch */
params
->
in_pitch
=
rsz_conf_chan
->
register_config
.
rsz_sdr_inoff
&
~
(
RSZ_SDR_INOFF_OFFSET_MASK
);
/* getting the output horizontal size */
params
->
out_hsize
=
rsz_conf_chan
->
register_config
.
rsz_out_size
&
~
(
RSZ_OUT_SIZE_HORZ_MASK
);
/* getting the vertical size */
params
->
out_vsize
=
((
rsz_conf_chan
->
register_config
.
rsz_out_size
&
~
(
RSZ_OUT_SIZE_VERT_MASK
))
>>
RSZ_OUT_VSIZE_SHIFT
);
/* getting the output pitch */
params
->
out_pitch
=
rsz_conf_chan
->
register_config
.
rsz_sdr_outoff
&
~
(
RSZ_SDR_OUTOFF_OFFSET_MASK
);
/* getting the chrominance algorithm */
params
->
cbilin
=
((
rsz_conf_chan
->
register_config
.
rsz_cnt
&
RSZ_CNT_CBILIN_MASK
)
>>
SET_BIT_CBLIN
);
/* getting the input type */
params
->
inptyp
=
((
rsz_conf_chan
->
register_config
.
rsz_cnt
&
RSZ_CNT_INPTYP_MASK
)
>>
SET_BIT_INPTYP
);
/* getting the starting pixel in horizontal direction */
params
->
horz_starting_pixel
=
((
rsz_conf_chan
->
register_config
.
rsz_in_start
&
~
(
RSZ_IN_START_HORZ_ST_MASK
)));
/* getting the starting pixel in vertical direction */
params
->
vert_starting_pixel
=
((
rsz_conf_chan
->
register_config
.
rsz_in_start
&
~
(
RSZ_IN_START_VERT_ST_MASK
))
>>
RSZ_IN_SIZE_VERT_SHIFT
);
/* getting the horizontal starting phase */
params
->
hstph
=
((
rsz_conf_chan
->
register_config
.
rsz_cnt
&
~
(
RSZ_HSTPH_MASK
)
>>
RSZ_HSTP_SHIFT
));
/* getting the vertical starting phase */
params
->
vstph
=
((
rsz_conf_chan
->
register_config
.
rsz_cnt
&
~
(
RSZ_VSTPH_MASK
)
>>
RSZ_VSTPH_SHIFT
));
for
(
coeffcounter
=
ZERO
;
coeffcounter
<
MAX_COEF_COUNTER
;
coeffcounter
++
)
{
/* getting the horizontal coefficients 0 */
params
->
hfilt_coeffs
[
2
*
coeffcounter
]
=
rsz_conf_chan
->
register_config
.
rsz_coeff_horz
[
coeffcounter
]
&
~
(
RSZ_FILTER_COEFF0_MASK
);
/* getting the horizontal coefficients 1 */
params
->
hfilt_coeffs
[
2
*
coeffcounter
+
NEXT
]
=
((
rsz_conf_chan
->
register_config
.
rsz_coeff_horz
[
coeffcounter
]
&
~
(
RSZ_FILTER_COEFF1_MASK
))
>>
RSZ_FILTER_COEFF_SHIFT
);
/* getting the vertical coefficients 0 */
params
->
vfilt_coeffs
[
2
*
coeffcounter
]
=
rsz_conf_chan
->
register_config
.
rsz_coeff_vert
[
coeffcounter
]
&
~
(
RSZ_FILTER_COEFF0_MASK
);
/* getting the vertical coefficients 1 */
params
->
vfilt_coeffs
[
2
*
coeffcounter
+
NEXT
]
=
((
rsz_conf_chan
->
register_config
.
rsz_coeff_vert
[
coeffcounter
]
&
~
(
RSZ_FILTER_COEFF1_MASK
))
>>
RSZ_FILTER_COEFF_SHIFT
);
}
/* getting the parameters for luma :- algo */
params
->
yenh_params
.
type
=
((
rsz_conf_chan
->
register_config
.
rsz_yehn
&
~
(
RSZ_YEHN_ALGO_MASK
))
>>
RSZ_YENH_TYPE_SHIFT
);
/* getting the parameters for luma :- core */
params
->
yenh_params
.
core
=
(
rsz_conf_chan
->
register_config
.
rsz_yehn
&
~
(
RSZ_YEHN_CORE_MASK
));
/* Coefficinets of parameters for luma :- gain */
params
->
yenh_params
.
gain
=
((
rsz_conf_chan
->
register_config
.
rsz_yehn
&
~
(
RSZ_YEHN_GAIN_MASK
))
>>
RSZ_YENH_GAIN_SHIFT
);
/* Coefficinets of parameters for luma :- SLOP configuration */
params
->
yenh_params
.
slop
=
((
rsz_conf_chan
->
register_config
.
rsz_yehn
&
~
(
RSZ_YEHN_SLOP_MASK
))
>>
RSZ_YENH_SLOP_SHIFT
);
/* getting the input type */
params
->
pix_fmt
=
((
rsz_conf_chan
->
register_config
.
rsz_cnt
&
RSZ_CNT_PIXFMT_MASK
)
>>
SET_BIT_YCPOS
);
if
(
params
->
pix_fmt
)
params
->
pix_fmt
=
RSZ_PIX_FMT_UYVY
;
else
params
->
pix_fmt
=
RSZ_PIX_FMT_YUYV
;
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
static
void
rsz_calculate_crop
(
channel_config_t
*
rsz_conf_chan
,
rsz_cropsize_t
*
cropsize
)
{
int
luma_enable
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
cropsize
->
hcrop
=
ZERO
;
cropsize
->
vcrop
=
ZERO
;
luma_enable
=
((
rsz_conf_chan
->
register_config
.
rsz_yehn
&
~
(
RSZ_YEHN_ALGO_MASK
))
>>
RSZ_YENH_TYPE_SHIFT
);
/* Luma enhancement reduces image width 1 pixels from left,right */
if
(
luma_enable
)
{
cropsize
->
hcrop
+=
2
;
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
}
/*
=====================free_buff===========================
this function free the input and output buffers alloated
*/
static
int
free_buff
(
channel_config_t
*
rsz_conf_chan
)
{
int
buffercounter
=
ZERO
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* Free all the input buffers */
while
(
rsz_conf_chan
->
input_buffer
[
buffercounter
]
!=
NULL
&&
buffercounter
<
MAX_INPUT_BUFFERS
)
{
/* free the memory */
rsz_free_pages
((
unsigned
long
)
rsz_conf_chan
->
input_buffer
[
buffercounter
],
rsz_conf_chan
->
in_bufsize
);
/* assign buffer zero to indicate its free */
rsz_conf_chan
->
input_buffer
[
buffercounter
]
=
NULL
;
buffercounter
++
;
}
buffercounter
=
ZERO
;
/* free all the output buffers */
while
(
rsz_conf_chan
->
output_buffer
[
buffercounter
]
!=
NULL
&&
buffercounter
<
MAX_INPUT_BUFFERS
)
{
/* free the memory */
rsz_free_pages
((
unsigned
long
)
rsz_conf_chan
->
output_buffer
[
buffercounter
],
rsz_conf_chan
->
out_bufsize
);
/* assign buffer zero to indicate its free */
rsz_conf_chan
->
output_buffer
[
buffercounter
]
=
NULL
;
buffercounter
++
;
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/*
=====================rsz_open===========================
This function creates a channels.
*/
static
int
rsz_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
channel_config_t
*
rsz_conf_chan
;
int
buffercounter
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
if
(
filp
->
f_flags
==
O_NONBLOCK
)
return
-
1
;
/* if usage counter is greater than maximum supported channels
return error */
if
(
device_config
.
module_usage_count
>=
MAX_CHANNELS
)
{
dev_err
(
rsz_device
,
"
\n
modules usage count is greater than supported "
);
return
-
EBUSY
;
}
/* allocate memory for a new configuration */
rsz_conf_chan
=
kmalloc
(
sizeof
(
channel_config_t
),
GFP_KERNEL
);
if
(
rsz_conf_chan
==
NULL
)
{
dev_err
(
rsz_device
,
"
\n
cannot allocate memory ro channel config"
);
return
-
ENOMEM
;
}
dev_dbg
(
rsz_device
,
"Malloc Done for channel configuration structure
\n
"
);
/* zeroing register config */
memset
(
&
(
rsz_conf_chan
->
register_config
),
ZERO
,
sizeof
(
resizer_config_t
));
/* increment usage counter */
/* Lock the global variable and increment the counter */
down_interruptible
(
&
device_config
.
device_mutex
);
device_config
.
module_usage_count
++
;
up
(
&
device_config
.
device_mutex
);
/*STATE_NOT_CONFIGURED and priority to zero */
rsz_conf_chan
->
config_state
=
STATE_NOT_CONFIGURED
;
/* Set priority to lowest for that configuration channel */
rsz_conf_chan
->
priority
=
MIN_PRIORITY
;
rsz_conf_chan
->
status
=
CHANNEL_FREE
;
/*Set configuration structure's input_buffer and output_buffer */
/*pointers to NULL */
for
(
buffercounter
=
ZERO
;
buffercounter
<
MAX_INPUT_BUFFERS
;
buffercounter
++
)
{
/* Help to initialize the input buffer to zero */
rsz_conf_chan
->
input_buffer
[
buffercounter
]
=
NULL
;
}
for
(
buffercounter
=
ZERO
;
buffercounter
<
MAX_OUTPUT_BUFFERS
;
buffercounter
++
)
{
/* Help to initialize the output buffer to zero */
rsz_conf_chan
->
output_buffer
[
buffercounter
]
=
NULL
;
}
dev_dbg
(
rsz_device
,
"Initializing of channel done
\n
"
);
/* Initializing of application mutex */
#ifdef CONFIG_PREEMPT_RT
init_completion
(
&
(
rsz_conf_chan
->
channel_sem
));
rsz_conf_chan
->
channel_sem
.
done
=
0
;
#else
init_MUTEX_LOCKED
(
&
(
rsz_conf_chan
->
channel_sem
));
#endif
init_MUTEX
(
&
(
rsz_conf_chan
->
chanprotection_sem
));
/* taking the configuartion structure in private data */
filp
->
private_data
=
rsz_conf_chan
;
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/* End of resizer open */
/*
=====================rsz_release===========================
The Function is used to release the number of resources occupied
by the channel
*/
static
int
rsz_release
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
/* get the configuratin of this channel from private_date member of
file */
int
ret
=
0
;
channel_config_t
*
rsz_conf_chan
=
(
channel_config_t
*
)
filp
->
private_data
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
ret
=
down_trylock
(
&
(
rsz_conf_chan
->
chanprotection_sem
));
if
(
ret
!=
0
)
{
dev_dbg
(
rsz_device
,
"Channel in use %d"
,
ret
);
return
-
EBUSY
;
}
/* It will free all the input and output buffers */
free_buff
(
rsz_conf_chan
);
/* Decrements the module usage count; */
/* Lock the global variable and decrement variable */
down_interruptible
(
&
device_config
.
device_mutex
);
device_config
.
module_usage_count
--
;
up
(
&
device_config
.
device_mutex
);
kfree
(
rsz_conf_chan
);
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
up
(
&
(
rsz_conf_chan
->
chanprotection_sem
));
return
SUCESS
;
}
/* End of function resizer_release */
/*
=====================rsz_mmap===========================
Function to map device memory into user space
*/
static
int
rsz_mmap
(
struct
file
*
filp
,
struct
vm_area_struct
*
vma
)
{
/* get the configuratin of this channel from private_date
member of file */
/* for looping purpuse */
int
buffercounter
=
ZERO
;
/* for checking purpose */
int
flag
=
ZERO
;
/* Hold number of input and output buffer allocated */
int
in_numbuffers
=
ZERO
,
out_numbuffers
=
ZERO
;
int
buffer_offset
;
unsigned
int
offset
=
vma
->
vm_pgoff
<<
PAGE_SHIFT
;
channel_config_t
*
rsz_conf_chan
=
(
channel_config_t
*
)
filp
->
private_data
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* Count the number of input buffers allocated */
while
((
rsz_conf_chan
->
input_buffer
[
buffercounter
])
!=
NULL
)
{
in_numbuffers
++
;
buffercounter
++
;
}
buffercounter
=
ZERO
;
/* To Count the number of output buffers allocated */
while
((
rsz_conf_chan
->
output_buffer
[
buffercounter
])
!=
NULL
)
{
out_numbuffers
++
;
buffercounter
++
;
}
/*Find the input address which is to be mapped */
for
(
buffercounter
=
ZERO
;
buffercounter
<
in_numbuffers
;
buffercounter
++
)
{
buffer_offset
=
virt_to_phys
(
rsz_conf_chan
->
input_buffer
[
buffercounter
]);
if
(
buffer_offset
==
offset
)
{
flag
=
ADDRESS_FOUND
;
break
;
}
}
/*Find the output address which is to be mapped */
if
(
flag
==
ZERO
)
{
for
(
buffercounter
=
ZERO
;
buffercounter
<
out_numbuffers
;
buffercounter
++
)
{
buffer_offset
=
virt_to_phys
(
rsz_conf_chan
->
output_buffer
[
buffercounter
]);
if
(
buffer_offset
==
offset
)
{
flag
=
ADDRESS_FOUND
;
break
;
}
}
}
/* The address to be mapped is not found so return error */
if
(
flag
==
ZERO
)
return
-
EAGAIN
;
dev_dbg
(
rsz_device
,
"The address mapped via mmap"
);
/* map the address from user space to kernel space */
if
(
remap_pfn_range
(
vma
,
vma
->
vm_start
,
vma
->
vm_pgoff
,
vma
->
vm_end
-
vma
->
vm_start
,
vma
->
vm_page_prot
))
{
return
-
EAGAIN
;
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
/* End of Function resizer_mmap */
/*
=====================rsz_ioctl===========================
This function will process IOCTL commands sent by
the application and
control the device IO operations.
*/
static
int
rsz_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
ret
=
ZERO
;
/*get the configuratin of this channel from
private_date member of file */
channel_config_t
*
rsz_conf_chan
=
(
channel_config_t
*
)
file
->
private_data
;
/* Create the structures of
different parameters passed by user */
rsz_priority_t
*
prio
;
rsz_status_t
*
status
;
rsz_resize_t
*
resize
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
ret
=
down_trylock
(
&
(
rsz_conf_chan
->
chanprotection_sem
));
if
(
ret
!=
0
)
{
//dev_dbg(rsz_device, "Channel in use", ret);
return
-
EBUSY
;
}
/* Before decoding check for correctness of cmd */
if
(
_IOC_TYPE
(
cmd
)
!=
RSZ_IOC_BASE
)
{
dev_err
(
rsz_device
,
"Bad command Value
\n
"
);
return
-
1
;
}
if
(
_IOC_NR
(
cmd
)
>
RSZ_IOC_MAXNR
)
{
dev_err
(
rsz_device
,
"Bad command Value
\n
"
);
return
-
1
;
}
/*veryfying access permission of commands */
if
(
_IOC_DIR
(
cmd
)
&
_IOC_READ
)
ret
=
!
access_ok
(
VERIFY_WRITE
,
(
void
*
)
arg
,
_IOC_SIZE
(
cmd
));
else
if
(
_IOC_DIR
(
cmd
)
&
_IOC_WRITE
)
ret
=
!
access_ok
(
VERIFY_READ
,
(
void
*
)
arg
,
_IOC_SIZE
(
cmd
));
if
(
ret
)
{
dev_err
(
rsz_device
,
"access denied
\n
"
);
return
-
1
;
/*error in access */
}
/* switch according value of cmd */
switch
(
cmd
)
{
/*This ioctl is used to request frame buffers to be
allocated by the RSZ module. The allocated buffers
are channel specific and can be addressed
by indexing */
case
RSZ_REQBUF
:
/* Function to allocate the memory to input
or output buffer. */
ret
=
malloc_buff
((
rsz_reqbufs_t
*
)
arg
,
rsz_conf_chan
);
break
;
/*This ioctl is used to query the physical address of a
particular frame buffer. */
case
RSZ_QUERYBUF
:
/* Function to query the physical address of
the buffer requested by index. */
ret
=
get_buf_address
((
rsz_buffer_t
*
)
arg
,
rsz_conf_chan
);
break
;
/* This ioctl is used to set the priority of the current
logical channel. If multiple resizing tasks from multiple
logical channels are currently *pending, the task
associated with the highest priority logical channel
will be executed first. */
case
RSZ_S_PRIORITY
:
dev_dbg
(
rsz_device
,
"
\n
resizer_Priority:start"
);
prio
=
(
rsz_priority_t
*
)
arg
;
/* Check the prioroty range and assign the priority */
if
(
prio
->
priority
>
MAX_PRIORITY
||
prio
->
priority
<
MIN_PRIORITY
)
return
-
EINVAL
;
else
{
rsz_conf_chan
->
priority
=
prio
->
priority
;
}
dev_dbg
(
rsz_device
,
"
\n
resizer_Priority:end"
);
break
;
/* This ioctl is used to get the priority of
the current logic channel */
case
RSZ_G_PRIORITY
:
dev_dbg
(
rsz_device
,
"
\n
Get resizer_Priority:start"
);
prio
=
(
rsz_priority_t
*
)
arg
;
/* Get the priority from the channel */
prio
->
priority
=
rsz_conf_chan
->
priority
;
dev_dbg
(
rsz_device
,
"
\n
Get resizer_Priority:end"
);
break
;
/* This ioctl is used to set the parameters
of the Resizer hardware, including input and output
image size, horizontal and vertical poly-phase
filter coefficients,luma enchancement filter coefficients etc */
case
RSZ_S_PARAM
:
/* Function to set the hardware configuration */
ret
=
rsz_set_params
((
rsz_params_t
*
)
arg
,
rsz_conf_chan
);
break
;
/*This ioctl is used to get the Resizer hardware settings
associated with the current logical channel represented
by fd. */
case
RSZ_G_PARAM
:
/* Function to get the hardware configuration */
ret
=
rsz_get_params
((
rsz_params_t
*
)
arg
,
rsz_conf_chan
);
break
;
/* This ioctl is used to check the current status
of the Resizer hardware */
case
RSZ_G_STATUS
:
status
=
(
rsz_status_t
*
)
arg
;
status
->
chan_busy
=
rsz_conf_chan
->
status
;
status
->
hw_busy
=
isbusy
();
status
->
src
=
INPUT_RAM
;
break
;
/*This ioctl submits a resizing task specified by the
rsz_resize structure.The call can either be blocked until
the task is completed or returned immediately based
on the value of the blocking argument in the rsz_resize
structure. If it is blocking, the status of the task
can be checked by calling ioctl RSZ_G_STATUS. Only one task
can be outstanding for each logical channel. */
case
RSZ_RESIZE
:
dev_dbg
(
rsz_device
,
"Beofre rsz_resize: PCR =%x"
,
regr
(
PCR
));
resize
=
(
rsz_resize_t
*
)
arg
;
ret
=
rsz_start
((
rsz_resize_t
*
)
arg
,
rsz_conf_chan
);
break
;
case
RSZ_GET_CROPSIZE
:
rsz_calculate_crop
(
rsz_conf_chan
,
(
rsz_cropsize_t
*
)
arg
);
break
;
case
RSZ_S_EXP
:
dev_dbg
(
rsz_device
,
"Before rsz_s_exp:SDR_REQ_EXP = %x"
,
regr
(
SDR_REQ_EXP
));
rsz_set_exp
(
*
((
int
*
)
arg
));
break
;
default:
dev_dbg
(
rsz_device
,
"resizer_ioctl: Invalid Command Value"
);
ret
=
-
EINVAL
;
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
up
(
&
(
rsz_conf_chan
->
chanprotection_sem
));
return
ret
;
}
/*End of function IOCTL */
static
struct
file_operations
rsz_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
rsz_open
,
.
release
=
rsz_release
,
.
mmap
=
rsz_mmap
,
.
ioctl
=
rsz_ioctl
,
};
/*
=====================rsz_isr===========================
Function to register the Resizer character device driver
*/
static
irqreturn_t
rsz_isr
(
int
irq
,
void
*
dev_id
)
{
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* to suggest that resizing has been completed */
complete
(
&
(
device_config
.
sem_isr
));
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
IRQ_HANDLED
;
}
static
struct
class
*
rsz_class
=
NULL
;
static
struct
miscdevice
resizer_device
=
{
.
minor
=
MISC_DYNAMIC_MINOR
,
.
name
=
"davinci_resizer"
,
.
fops
=
&
rsz_fops
,
};
/*
=====================rsz_init===========================
function to register resizer character driver
*/
static
int
__init
rsz_init
(
void
)
{
int
result
;
device_config
.
module_usage_count
=
ZERO
;
device_config
.
array_count
=
ZERO
;
/* Register the driver in the kernel */
result
=
alloc_chrdev_region
(
&
dev
,
ZERO
,
1
,
DRIVER_NAME
);
if
(
result
<
ZERO
)
{
printk
(
"
\n
DaVinciresizer: Module intialization failed.\
could not register character device"
);
return
-
ENODEV
;
}
/* Initialize of character device */
cdev_init
(
&
c_dev
,
&
rsz_fops
);
c_dev
.
owner
=
THIS_MODULE
;
c_dev
.
ops
=
&
rsz_fops
;
/* addding character device */
result
=
cdev_add
(
&
c_dev
,
dev
,
1
);
if
(
result
)
{
printk
(
"NOtICE
\n
DaVinciresizer:Error %d adding Davinciresizer\
..error no:"
,
result
);
unregister_chrdev_region
(
dev
,
1
);
return
result
;
}
/* registeration of character device */
register_chrdev
(
MAJOR
(
dev
),
DRIVER_NAME
,
&
rsz_fops
);
/* register driver as a platform driver */
if
(
misc_register
(
&
resizer_device
))
{
printk
(
KERN_ERR
"Unable to register resizer device.
\n
"
);
return
-
EINVAL
;
}
rsz_class
=
class_create
(
THIS_MODULE
,
"davinci_resizer"
);
if
(
!
rsz_class
)
{
printk
(
KERN_ERR
"Unalbe to create resizer class.
\n
"
);
return
-
EIO
;
}
/* register simple device class */
device_create
(
rsz_class
,
NULL
,
dev
,
NULL
,
"davinci_resizer"
);
init_completion
(
&
(
device_config
.
sem_isr
));
device_config
.
sem_isr
.
done
=
ZERO
;
/* Initialize the device mutex */
init_MUTEX
(
&
device_config
.
array_sem
);
init_MUTEX
(
&
device_config
.
device_mutex
);
/* Set up the Interrupt handler for resizer interrupt */
result
=
request_irq
(
IRQ_RSZINT
,
rsz_isr
,
IRQF_DISABLED
,
"dm644xresizer"
,
(
void
*
)
NULL
);
if
(
result
<
ZERO
)
{
printk
(
"Cannot initialize IRQ
\n
"
);
return
result
;
}
rsz_set_exp
(
0xe
);
rsz_device
=
resizer_device
.
this_device
;
return
SUCESS
;
}
/* End of function resizer_init */
/*
=====================rsz_cleanup===========================
Function is called by the kernel. It unregister the device.
*/
void
__exit
rsz_cleanup
(
void
)
{
unregister_chrdev_region
(
dev
,
1
);
/* remove simple class device */
device_destroy
(
rsz_class
,
dev
);
/* destroy simple class */
class_destroy
(
rsz_class
);
/* Remove platform driver */
misc_deregister
(
&
resizer_device
);
/* disable interrupt */
free_irq
(
IRQ_RSZINT
,
(
void
*
)
NULL
);
cdev_del
(
&
c_dev
);
/* unregistering the driver from the kernel */
unregister_chrdev
(
MAJOR
(
dev
),
DRIVER_NAME
);
}
/* End of function resizer_cleanup */
module_init
(
rsz_init
)
module_exit
(
rsz_cleanup
)
drivers/char/davinci_resizer.h
0 → 100644
View file @
d5c8226e
/* *
* Copyright (C) 2006 Texas Instruments Inc
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not,write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* davinci_resizer.h file */
#ifndef DAVINVI_RESIZER_H
#define DAVINVI_RESIZER_H
/* ioctls definition */
#pragma pack(1)
#define RSZ_IOC_BASE 'R'
#define RSZ_IOC_MAXNR 11
/*Ioctl options which are to be passed while calling the ioctl*/
#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE,1,rsz_reqbufs_t*)
#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE,2,rsz_buffer_t *)
#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE,3,rsz_params_t *)
#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE,4,rsz_params_t *)
#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE,5,rsz_resize_t *)
#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE,6,rsz_status_t *)
#define RSZ_S_PRIORITY _IOWR(RSZ_IOC_BASE,7,rsz_priority_t*)
#define RSZ_G_PRIORITY _IOWR(RSZ_IOC_BASE,9,rsz_priority_t*)
#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE,10,rsz_cropsize_t *)
#define RSZ_S_EXP _IOWR(RSZ_IOC_BASE,11,int*)
#pragma pack()
/* End of ioctls */
#define RSZ_BUF_IN 0
#define RSZ_BUF_OUT 1
#define RSZ_YENH_DISABLE 0
#define RSZ_YENH_3TAP_HPF 1
#define RSZ_YENH_5TAP_HPF 2
#ifdef __KERNEL__
/* Defines and Constants*/
#define MAX_BUFFER 3
#define MAX_CHANNELS 16
#define MAX_PRIORITY 5
#define MIN_PRIORITY 0
#define DEFAULT_PRIORITY 3
#define MAX_IMAGE_WIDTH 1280
#define MAX_IMAGE_WIDTH_HIGH 640
#define MAX_IMAGE_HEIGHT 960
#define MAX_INPUT_BUFFERS 8
#define MAX_OUTPUT_BUFFERS 8
#define DRIVER_NAME "Resizer"
#define FREE_BUFFER 0
#define ALIGNMENT 16
#define CHANNEL_BUSY 1
#define CHANNEL_FREE 0
#define PIXEL_EVEN 2
#define RATIO_MULTIPLIER 256
/*Bit position Macro*/
/* macro for bit set and clear */
#define BITSET(variable,bit) ((variable)| (1<<bit))
#define BITRESET(variable,bit) ((variable)& (~(0x00000001<<(bit))))
/* RSZ_CNT */
#define CSL_RESZ_RSZ_CNT_CBILIN_MASK (0x20000000u)
#define CSL_RESZ_RSZ_CNT_CBILIN_SHIFT (0x0000001Du)
/*RSZ_OUT_VSIZE_SHIFT*/
#define RSZ_VSTPH_MASK (0xfC7fffffu)
#define RSZ_HSTPH_MASK (0xff8fffffu)
#define RSZ_CNT_VRSZ_MASK (0xfff002ffu)
#define RSZ_CNT_HRSZ_MASK (0xfffffc00u)
/* OUT_SIZE */
#define RSZ_OUT_SIZE_VERT_MASK (0xf800ffffu)
#define RSZ_OUT_SIZE_HORZ_MASK (0xfffff800u)
/* IN_START */
#define RSZ_IN_START_VERT_ST_MASK (0xE000FFFFu)
#define RSZ_IN_START_HORZ_ST_MASK (0xFFFFE000u)
/* IN_SIZE */
#define RSZ_IN_SIZE_VERT_MASK (0xe000ffffu)
#define RSZ_IN_SIZE_HORZ_MASK (0xffffe000u)
/* SDR_INOFF */
#define RSZ_SDR_INOFF_OFFSET_MASK (0xffff0000u)
#define RSZ_SDR_OUTOFF_OFFSET_MASK (0xffff0000u)
/**/
#define RSZ_UWORD_MASK (0x03FF0000u)
#define RSZ_LWORD_MASK (0x000003FFu)
/* YENH */
#define RSZ_YEHN_CORE_MASK (0xffffff00u)
#define RSZ_YEHN_SLOP_MASK (0xfffff0ffu)
#define RSZ_YEHN_GAIN_MASK (0xffff0fffu)
#define RSZ_YEHN_ALGO_MASK (0xfffcffffu)
/* Filter coeefceints */
#define RSZ_FILTER_COEFF0_MASK (0xfffffc00u)
#define RSZ_FILTER_COEFF1_MASK (0xfc00ffffu)
#define RSZ_CNT_CBILIN_MASK (0x20000000u)
#define RSZ_CNT_INPTYP_MASK (0x08000000u)
#define RSZ_CNT_PIXFMT_MASK (0x04000000u)
#define RSZ_HSTP_SHIFT 20
#define RSZ_HRSZ_MASK (0xfffffc00)
#define RSZ_VRSZ_MASK (0xfff003ff)
#define RSZ_VRSZ_SHIFT 10
/*///////Shifts*/
#define RSZ_OUT_VSIZE_SHIFT 16
#define SET_BIT_CBLIN 29
#define SET_BIT_INPUTRAM 28
#define INPUT_RAM 1
#define SET_BIT_INPTYP 27
#define SET_BIT_YCPOS 26
#define RSZ_VSTPH_SHIFT 23
#define RSZ_FILTER_COEFF_SHIFT 16
#define RSZ_YENH_TYPE_SHIFT 16
#define RSZ_YENH_GAIN_SHIFT 12
#define RSZ_YENH_SLOP_SHIFT 8
#define UP_RSZ_RATIO 64
#define DOWN_RSZ_RATIO 512
#define UP_RSZ_RATIO1 513
#define DOWN_RSZ_RATIO1 1024
#define SET_ENABLE_BIT 0
#define RSZ_IN_SIZE_VERT_SHIFT 16
#define MAX_HORZ_PIXEL_8BIT 31
#define MAX_HORZ_PIXEL_16BIT 15
#define BYTES_PER_PIXEL 2
#define NUM_PHASES 8
#define NUM_TAPS 4
#define NUM_D2PH 4
/* for downsampling
2+x ~ 4x, numberof phases */
#define NUM_D2TAPS 7
/* for downsampling
2+x ~ 4x,number of taps */
#define NUM_COEFS (NUM_PHASES * NUM_TAPS)
#define ALIGN32 32
#define ADDRESS_FOUND 1
#define NEXT 1
/*#define DEBUG 0*/
#define RESIZER_IOBASE_VADDR IO_ADDRESS(0x01C70C00)
#define MAX_COEF_COUNTER 16
#define ZERO 0
#define FIRSTENTRY 0
#define SECONDENTRY 1
#define EMPTY 0
#define SUCESS 0
#endif
/* end of #ifdef __KERNEL__ */
#define RSZ_INTYPE_YCBCR422_16BIT 0
#define RSZ_INTYPE_PLANAR_8BIT 1
#define RSZ_PIX_FMT_PLANAR 2
/* 8-bit planar input */
#define RSZ_PIX_FMT_UYVY 0
/* cb:y:cr:y */
#define RSZ_PIX_FMT_YUYV 1
/* y:cb:y:cr */
#ifdef __KERNEL__
#define isbusy() ((regr(PCR) & 0x02)>>1)
/*///////Enumerations*/
enum
config_done
{
STATE_CONFIGURED
,
/* Resizer driver configured by application */
STATE_NOT_CONFIGURED
/* Resizer driver not configured by
application */
};
#endif
/* end of #ifdef __KERNEL__ */
/*Structure Definitions*/
/* To allocate the memory*/
typedef
struct
rsz_reqbufs
{
int
buf_type
;
/* type of frame buffer */
int
size
;
/* size of the frame bufferto be allocated */
int
count
;
/* number of frame buffer to be allocated */
}
rsz_reqbufs_t
;
/* assed for quering the buffer to get physical address*/
typedef
struct
rsz_buffer
{
int
index
;
/* buffer index number, 0 -> N-1 */
int
buf_type
;
/* buffer type, input or output */
int
offset
;
/* physical address of the buffer,
used in the mmap() system call */
int
size
;
}
rsz_buffer_t
;
/* used to luma enhancement options*/
typedef
struct
rsz_yenh
{
int
type
;
/* represents luma enable or disable */
unsigned
char
gain
;
/*represents gain */
unsigned
char
slop
;
/*represents slop */
unsigned
char
core
;
/* Represents core value */
}
rsz_yenh_t
;
/* Conatins all the parameters for resizing . This structure
is used to configure resiser parameters*/
typedef
struct
rsz_params
{
int
in_hsize
;
/* input frame horizontal size */
int
in_vsize
;
/* input frame vertical size */
int
in_pitch
;
/* offset between two rows of input frame */
int
inptyp
;
/* for determining 16 bit or 8 bit data */
int
vert_starting_pixel
;
/* for specifying vertical
starting pixel in input */
int
horz_starting_pixel
;
/* for specyfing horizontal
starting pixel in input */
int
cbilin
;
/* # defined, filter with luma or bi-linear
interpolation */
int
pix_fmt
;
/* # defined, UYVY or YUYV */
int
out_hsize
;
/* output frame horizontal size */
int
out_vsize
;
/* output frame vertical size */
int
out_pitch
;
/* offset between two rows of output frame */
int
hstph
;
/* for specifying horizontal starting phase */
int
vstph
;
/* for specifying vertical starting phase */
short
hfilt_coeffs
[
32
];
/* horizontal filter coefficients */
short
vfilt_coeffs
[
32
];
/* vertical filter coefficients */
rsz_yenh_t
yenh_params
;
}
rsz_params_t
;
/* resize structure passed during the resize IOCTL*/
typedef
struct
rsz_resize
{
rsz_buffer_t
in_buf
;
rsz_buffer_t
out_buf
;
}
rsz_resize_t
;
/* Contains the status of hardware and channel*/
typedef
struct
rsz_status
{
int
chan_busy
;
/* 1: channel is busy, 0: channel is not busy */
int
hw_busy
;
/*1: hardware is busy, 0:
hardware is not busy */
int
src
;
/* # defined, can be either
SD-RAM or CCDC/PREVIEWER */
}
rsz_status_t
;
/* structure to set the priroity of the the channel*/
typedef
struct
rsz_priority
{
int
priority
;
/* 0=>5, with 5 the highest priority */
}
rsz_priority_t
;
/* Passed by application for getting crop size*/
typedef
struct
rsz_cropsize
{
unsigned
int
hcrop
;
/*number of pixels per line c
ropped in output image */
unsigned
int
vcrop
;
/*number of lines cropped
in output image */
}
rsz_cropsize_t
;
#ifdef __KERNEL__
/*Register mapped structure which contains the every register
information*/
typedef
struct
resizer_config
{
int
rsz_pcr
;
/*pcr register mapping variable */
int
rsz_in_start
;
/* in_start register mapping variable */
int
rsz_in_size
;
/* in_size register mapping variable */
int
rsz_out_size
;
/* out_size register mapping variable */
int
rsz_cnt
;
/* rsz_cnt register mapping variable */
int
rsz_sdr_inadd
;
/* sdr_inadd register mapping variable */
int
rsz_sdr_inoff
;
/* sdr_inoff register mapping variable */
int
rsz_sdr_outadd
;
/* sdr_outadd register mapping variable */
int
rsz_sdr_outoff
;
/* sdr_outbuff register mapping variable */
int
rsz_coeff_horz
[
16
];
/* horizontal coefficients mapping array */
int
rsz_coeff_vert
[
16
];
/* vertical coefficients mapping array */
int
rsz_yehn
;
/* yehn(luma)register mapping variable */
}
resizer_config_t
;
/* Channel specific structure contains information regarding
the every channel */
typedef
struct
channel_config
{
resizer_config_t
register_config
;
/* instance of register set
mapping structure */
void
*
input_buffer
[
MAX_INPUT_BUFFERS
];
/* for storing input buffers
pointers */
void
*
output_buffer
[
MAX_OUTPUT_BUFFERS
];
/* for storing output
buffers pointers */
int
in_bufsize
,
out_bufsize
;
/* Contains input and output buffer size */
int
status
;
/* specifies whether the channel */
/* is busy or not */
int
priority
;
/* stores priority of the application */
#ifdef CONFIG_PREEMPT_RT
struct
completion
channel_sem
;
#else
struct
semaphore
channel_sem
;
#endif
struct
semaphore
chanprotection_sem
;
enum
config_done
config_state
;
}
channel_config_t
;
/*Global structure which contains information about number of chanels
and protection variables */
typedef
struct
device_params
{
int
module_usage_count
;
/* For counting no of channels
created */
struct
completion
sem_isr
;
/*Semaphore for interrupt */
struct
semaphore
array_sem
;
/* Semaphore for array */
struct
semaphore
device_mutex
;
/* mutex protecting device_params */
/* structure object */
channel_config_t
*
channel_configuration
[
MAX_CHANNELS
];
/* Pointer to channel configuration */
int
array_count
;
/* for counting number of elements
in arrray */
}
device_params_t
;
#endif
/* end of #ifdef __KERNEL__ */
#endif
/* End of #ifndef DAVINCI_RESIZER_H */
drivers/char/davinci_resizer_hw.c
0 → 100644
View file @
d5c8226e
/* *
* Copyright (C) 2006 Texas Instruments Inc
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* davinci_resizer_hw.c file */
/*Header files*/
#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
/* printk() */
#include <linux/device.h>
#include <linux/slab.h>
/* kmalloc() */
#include <linux/fs.h>
/* everything... */
#include <linux/errno.h>
/* error codes */
#include <linux/types.h>
/* size_t */
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/err.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#ifdef CONFIG_PREEMPT_RT
#include <linux/completion.h>
#endif
#include <asm/page.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include "davinci_resizer_hw.h"
#include "davinci_resizer.h"
extern
struct
device
*
rsz_device
;
/*
* functions definition
*/
void
rsz_hardware_setup
(
channel_config_t
*
rsz_conf_chan
);
int
rsz_enable
(
channel_config_t
*
rsz_conf_chan
);
int
rsz_writebuffer_status
(
void
);
/*
=====================rsz_hardware_setup===========================
Function to set hardware configuration registers
*/
void
rsz_hardware_setup
(
channel_config_t
*
rsz_conf_chan
)
{
/* Counter to set the value of horizonatl and vertical coeff */
int
coeffcounter
;
/* for getting the coefficient offset */
int
coeffoffset
=
ZERO
;
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* clear the VPSS_PCR register buffer overflow bits */
regw
(
0x003c0000
,
VPSS_PCR
);
/* setting the hardware register rszcnt */
regw
(
rsz_conf_chan
->
register_config
.
rsz_cnt
,
RSZ_CNT
);
dev_dbg
(
rsz_device
,
"RSZ CNT : %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_cnt
,
regr
(
RSZ_CNT
));
/* setting the hardware register instart */
regw
(
rsz_conf_chan
->
register_config
.
rsz_in_start
,
IN_START
);
dev_dbg
(
rsz_device
,
"In START %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_in_start
,
regr
(
IN_START
));
/* setting the hardware register insize */
regw
(
rsz_conf_chan
->
register_config
.
rsz_in_size
,
IN_SIZE
);
dev_dbg
(
rsz_device
,
"In size %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_in_size
,
regr
(
IN_SIZE
));
/* setting the hardware register outsize */
regw
(
rsz_conf_chan
->
register_config
.
rsz_out_size
,
OUT_SIZE
);
dev_dbg
(
rsz_device
,
"out size %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_out_size
,
regr
(
OUT_SIZE
));
/* setting the hardware register inaddress */
regw
(
rsz_conf_chan
->
register_config
.
rsz_sdr_inadd
,
SDR_INADD
);
dev_dbg
(
rsz_device
,
"in address %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_sdr_inadd
,
regr
(
SDR_INADD
));
/* setting the hardware register in offset */
regw
(
rsz_conf_chan
->
register_config
.
rsz_sdr_inoff
,
SDR_INOFF
);
dev_dbg
(
rsz_device
,
"in offset %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_sdr_inoff
,
regr
(
SDR_INOFF
));
/* setting the hardware register in offset */
/* setting the hardware register out address */
regw
(
rsz_conf_chan
->
register_config
.
rsz_sdr_outadd
,
SDR_OUTADD
);
dev_dbg
(
rsz_device
,
"out addrsess %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_sdr_outadd
,
regr
(
SDR_OUTADD
));
/* setting the hardware register in offset */
/* setting the hardware register out offset */
regw
(
rsz_conf_chan
->
register_config
.
rsz_sdr_outoff
,
SDR_OUTOFF
);
dev_dbg
(
rsz_device
,
"out offset %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_sdr_outoff
,
regr
(
SDR_OUTOFF
));
/* setting the hardware register yehn */
regw
(
rsz_conf_chan
->
register_config
.
rsz_yehn
,
YENH
);
dev_dbg
(
rsz_device
,
"yehn %x regr = %x
\n
"
,
rsz_conf_chan
->
register_config
.
rsz_yehn
,
regr
(
YENH
));
/* setting the hardware registers of coefficients */
for
(
coeffcounter
=
ZERO
;
coeffcounter
<
MAX_COEF_COUNTER
;
coeffcounter
++
)
{
regw
(
rsz_conf_chan
->
register_config
.
rsz_coeff_horz
[
coeffcounter
],
((
HFILT10
+
coeffoffset
)));
regw
(
rsz_conf_chan
->
register_config
.
rsz_coeff_vert
[
coeffcounter
],
((
VFILT10
+
coeffoffset
)));
coeffoffset
=
coeffoffset
+
COEFF_ADDRESS_OFFSET
;
}
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
}
/*
=====================rsz_enable===========================
Function to enable the resizer
*/
int
rsz_enable
(
channel_config_t
*
rsz_conf_chan
)
{
dev_dbg
(
rsz_device
,
"entering %s
\n
"
,
__FUNCTION__
);
/* Eanbling the resizer the setting enable bit */
rsz_conf_chan
->
register_config
.
rsz_pcr
=
BITSET
(
rsz_conf_chan
->
register_config
.
rsz_pcr
,
SET_ENABLE_BIT
);
regw
(
rsz_conf_chan
->
register_config
.
rsz_pcr
,
PCR
);
dev_dbg
(
rsz_device
,
"the value of pcr is %x
\n
"
,
regr
(
PCR
));
regw
(
0x003c0000
,
VPSS_PCR
);
dev_dbg
(
rsz_device
,
"leaving %s
\n
"
,
__FUNCTION__
);
return
SUCESS
;
}
int
rsz_writebuffer_status
(
void
)
{
dev_dbg
(
rsz_device
,
"VPSS_PCR: %x
\n
"
,
regr
(
VPSS_PCR
));
return
((
regr
(
VPSS_PCR
)
>>
18
)
&
0xF
);
}
drivers/char/davinci_resizer_hw.h
0 → 100644
View file @
d5c8226e
/* *
* Copyright (C) 2006 Texas Instruments Inc
*
* 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 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* davinci_resizer_hw.h file */
#ifndef DAVINCI_RESIZER_HW
#define DAVINCI_RESIZER_HW
/* Register offset mapping*/
#define RESIZER_IOBASE_VADDR IO_ADDRESS(0x01C70C00)
#define PID 0x0000
#define PCR 0x0004
#define RSZ_CNT 0x0008
#define OUT_SIZE 0x000C
#define IN_START 0x0010
#define IN_SIZE 0x0014
#define SDR_INADD 0x0018
#define SDR_INOFF 0x001C
#define SDR_OUTADD 0x0020
#define SDR_OUTOFF 0x0024
#define HFILT10 0x0028
#define VFILT10 0x0068
#define COEFF_ADDRESS_OFFSET 0x04
#define YENH 0x00A8
#define VPSS_PCR (0x3404-0x0C00)
#define SDR_REQ_EXP (0x3508-0x0C00)
/* Register read/write */
#define regw(val,reg) outl(val,((reg)+ RESIZER_IOBASE_VADDR))
#define regr(reg) inl((reg)+RESIZER_IOBASE_VADDR)
#endif
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