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
ca3e7676
Commit
ca3e7676
authored
Dec 08, 2009
by
Kevin Hilman
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'davinci-next-drivers' into davinci-reset
parents
114cf338
1e5c7c4d
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
2565 additions
and
11 deletions
+2565
-11
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm365-evm.c
+3
-0
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-davinci.c
+25
-4
drivers/input/misc/Kconfig
drivers/input/misc/Kconfig
+9
-0
drivers/input/misc/Makefile
drivers/input/misc/Makefile
+1
-0
drivers/input/misc/dm365evm_keys.c
drivers/input/misc/dm365evm_keys.c
+323
-0
drivers/video/Kconfig
drivers/video/Kconfig
+15
-0
drivers/video/Makefile
drivers/video/Makefile
+1
-0
drivers/video/davincifb.c
drivers/video/davincifb.c
+1734
-0
include/video/davincifb.h
include/video/davincifb.h
+442
-0
sound/soc/davinci/davinci-sffsdr.c
sound/soc/davinci/davinci-sffsdr.c
+12
-7
No files found.
arch/arm/mach-davinci/board-dm365-evm.c
View file @
ca3e7676
...
@@ -178,6 +178,9 @@ static struct at24_platform_data eeprom_info = {
...
@@ -178,6 +178,9 @@ static struct at24_platform_data eeprom_info = {
static
struct
snd_platform_data
dm365_evm_snd_data
;
static
struct
snd_platform_data
dm365_evm_snd_data
;
static
struct
i2c_board_info
i2c_info
[]
=
{
static
struct
i2c_board_info
i2c_info
[]
=
{
{
I2C_BOARD_INFO
(
"dm365evm_keys"
,
0x25
),
},
{
{
I2C_BOARD_INFO
(
"24c256"
,
0x50
),
I2C_BOARD_INFO
(
"24c256"
,
0x50
),
.
platform_data
=
&
eeprom_info
,
.
platform_data
=
&
eeprom_info
,
...
...
drivers/i2c/busses/i2c-davinci.c
View file @
ca3e7676
...
@@ -112,6 +112,7 @@ struct davinci_i2c_dev {
...
@@ -112,6 +112,7 @@ struct davinci_i2c_dev {
u8
*
buf
;
u8
*
buf
;
size_t
buf_len
;
size_t
buf_len
;
int
irq
;
int
irq
;
int
stop
;
u8
terminate
;
u8
terminate
;
struct
i2c_adapter
adapter
;
struct
i2c_adapter
adapter
;
};
};
...
@@ -249,9 +250,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -249,9 +250,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
u16
w
;
u16
w
;
int
r
;
int
r
;
if
(
msg
->
len
==
0
)
return
-
EINVAL
;
if
(
!
pdata
)
if
(
!
pdata
)
pdata
=
&
davinci_i2c_platform_data_default
;
pdata
=
&
davinci_i2c_platform_data_default
;
/* Introduce a delay, required for some boards (e.g Davinci EVM) */
/* Introduce a delay, required for some boards (e.g Davinci EVM) */
...
@@ -263,6 +261,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -263,6 +261,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev
->
buf
=
msg
->
buf
;
dev
->
buf
=
msg
->
buf
;
dev
->
buf_len
=
msg
->
len
;
dev
->
buf_len
=
msg
->
len
;
dev
->
stop
=
stop
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CNT_REG
,
dev
->
buf_len
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CNT_REG
,
dev
->
buf_len
);
...
@@ -280,6 +279,10 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -280,6 +279,10 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
flag
|=
DAVINCI_I2C_MDR_TRX
;
flag
|=
DAVINCI_I2C_MDR_TRX
;
if
(
stop
)
if
(
stop
)
flag
|=
DAVINCI_I2C_MDR_STP
;
flag
|=
DAVINCI_I2C_MDR_STP
;
if
(
msg
->
len
==
0
)
{
flag
|=
DAVINCI_I2C_MDR_RM
;
flag
&=
~
DAVINCI_I2C_MDR_STP
;
}
/* Enable receive or transmit interrupts */
/* Enable receive or transmit interrupts */
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
...
@@ -290,6 +293,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -290,6 +293,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
dev
->
terminate
=
0
;
dev
->
terminate
=
0
;
/* First byte should be set here, not after interrupt,
* because transmit-data-ready interrupt can come before
* NACK-interrupt during sending of previous message and
* ICDXR may have wrong data */
if
((
!
(
msg
->
flags
&
I2C_M_RD
))
&&
dev
->
buf_len
)
{
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_DXR_REG
,
*
dev
->
buf
++
);
dev
->
buf_len
--
;
}
/* write the data into mode register */
/* write the data into mode register */
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
);
...
@@ -371,7 +384,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
...
@@ -371,7 +384,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
static
u32
i2c_davinci_func
(
struct
i2c_adapter
*
adap
)
static
u32
i2c_davinci_func
(
struct
i2c_adapter
*
adap
)
{
{
return
I2C_FUNC_I2C
|
(
I2C_FUNC_SMBUS_EMUL
&
~
I2C_FUNC_SMBUS_QUICK
)
;
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
;
}
}
static
void
terminate_read
(
struct
davinci_i2c_dev
*
dev
)
static
void
terminate_read
(
struct
davinci_i2c_dev
*
dev
)
...
@@ -430,6 +443,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
...
@@ -430,6 +443,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
case
DAVINCI_I2C_IVR_ARDY
:
case
DAVINCI_I2C_IVR_ARDY
:
davinci_i2c_write_reg
(
dev
,
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_STR_REG
,
DAVINCI_I2C_STR_ARDY
);
DAVINCI_I2C_STR_REG
,
DAVINCI_I2C_STR_ARDY
);
if
(((
dev
->
buf_len
==
0
)
&&
(
dev
->
stop
!=
0
))
||
(
dev
->
cmd_err
&
DAVINCI_I2C_STR_NACK
))
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_MDR_STP
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
}
complete
(
&
dev
->
cmd_complete
);
complete
(
&
dev
->
cmd_complete
);
break
;
break
;
...
...
drivers/input/misc/Kconfig
View file @
ca3e7676
...
@@ -288,6 +288,15 @@ config INPUT_DM355EVM
...
@@ -288,6 +288,15 @@ config INPUT_DM355EVM
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called dm355evm_keys.
module will be called dm355evm_keys.
config INPUT_DM365EVM
tristate "TI DaVinci DM365 EVM IR Remote"
depends on MACH_DAVINCI_DM365_EVM
help
Supports the IR remote used with the DM365 EVM board.
To compile this driver as a module, choose M here: the
module will be called dm365evm_keys.
config INPUT_BFIN_ROTARY
config INPUT_BFIN_ROTARY
tristate "Blackfin Rotary support"
tristate "Blackfin Rotary support"
depends on BF54x || BF52x
depends on BF54x || BF52x
...
...
drivers/input/misc/Makefile
View file @
ca3e7676
...
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
...
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
obj-$(CONFIG_INPUT_CM109)
+=
cm109.o
obj-$(CONFIG_INPUT_CM109)
+=
cm109.o
obj-$(CONFIG_INPUT_COBALT_BTNS)
+=
cobalt_btns.o
obj-$(CONFIG_INPUT_COBALT_BTNS)
+=
cobalt_btns.o
obj-$(CONFIG_INPUT_DM355EVM)
+=
dm355evm_keys.o
obj-$(CONFIG_INPUT_DM355EVM)
+=
dm355evm_keys.o
obj-$(CONFIG_INPUT_DM365EVM)
+=
dm365evm_keys.o
obj-$(CONFIG_HP_SDC_RTC)
+=
hp_sdc_rtc.o
obj-$(CONFIG_HP_SDC_RTC)
+=
hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER)
+=
ixp4xx-beeper.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER)
+=
ixp4xx-beeper.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)
+=
keyspan_remote.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)
+=
keyspan_remote.o
...
...
drivers/input/misc/dm365evm_keys.c
0 → 100644
View file @
ca3e7676
/*
* dm365evm_keys.c - support IR remote on DM365 EVM board
*
* Copyright (c) 2009 by David Brownell
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
/*
* The MSP430 firmware on the DM365 EVM monitors an IR receptor used for
* the remote control. When any key is pressed, or its autorepeat kicks
* in, an event is sent. This driver read those events from the small
* event queue and reports them.
*
* Compared to the DM355 EVM: the MSP firmware does *only* IR. So this
* driver is simpler, and doesn't even need to use the MFD model.
*
* Note that physically there can only be one of these devices.
*
* This driver was tested with firmware revision 0xA1 (beta board).
*/
struct
dm365evm_keys
{
struct
input_dev
*
input
;
struct
i2c_client
*
i2c
;
};
#define DM365EVM_MSP_FIRMREV 0
#define DM365EVM_MSP_INPUT_LOW 1
#define DM365EVM_MSP_INPUT_HIGH 2
#define DM365EVM_MSP_INPUT_COUNT 3
#define DM365EVM_MSP_0x43 4
#define MSP430_GPIO 0
/* These initial keycodes can be remapped by dm365evm_setkeycode(). */
static
struct
{
u16
event
;
u16
keycode
;
}
dm365evm_keys
[]
=
{
/*
* IR buttons ... codes assigned to match the universal remote
* provided with the EVM (Philips PM4S) using DVD code 0020.
*
* These event codes match firmware documentation, but other
* remote controls could easily send more RC5-encoded events.
* The PM4S manual was used in several cases to help select
* a keycode reflecting the intended usage.
*
* RC5 codes are 14 bits, with two start bits (0x3 prefix)
* and a toggle bit (masked out below).
*/
{
0x300c
,
KEY_POWER
,
},
/* NOTE: docs omit this */
{
0x3000
,
KEY_NUMERIC_0
,
},
{
0x3001
,
KEY_NUMERIC_1
,
},
{
0x3002
,
KEY_NUMERIC_2
,
},
{
0x3003
,
KEY_NUMERIC_3
,
},
{
0x3004
,
KEY_NUMERIC_4
,
},
{
0x3005
,
KEY_NUMERIC_5
,
},
{
0x3006
,
KEY_NUMERIC_6
,
},
{
0x3007
,
KEY_NUMERIC_7
,
},
{
0x3008
,
KEY_NUMERIC_8
,
},
{
0x3009
,
KEY_NUMERIC_9
,
},
{
0x3022
,
KEY_ENTER
,
},
{
0x30ec
,
KEY_MODE
,
},
/* "tv/vcr/..." */
{
0x300f
,
KEY_SELECT
,
},
/* "info" */
{
0x3020
,
KEY_CHANNELUP
,
},
/* "up" */
{
0x302e
,
KEY_MENU
,
},
/* "in/out" */
{
0x3011
,
KEY_VOLUMEDOWN
,
},
/* "left" */
{
0x300d
,
KEY_MUTE
,
},
/* "ok" */
{
0x3010
,
KEY_VOLUMEUP
,
},
/* "right" */
{
0x301e
,
KEY_SUBTITLE
,
},
/* "cc" */
{
0x3021
,
KEY_CHANNELDOWN
,
},
/* "down" */
{
0x3022
,
KEY_PREVIOUS
,
},
{
0x3026
,
KEY_SLEEP
,
},
{
0x3172
,
KEY_REWIND
,
},
{
0x3175
,
KEY_PLAY
,
},
{
0x3174
,
KEY_FASTFORWARD
,
},
{
0x3177
,
KEY_RECORD
,
},
{
0x3176
,
KEY_STOP
,
},
{
0x3169
,
KEY_PAUSE
,
},
/* NOTE: SW22, a pushbutton next to the IR sensor, is also
* wired to the MSP430 but is currently ignored; some other
* I/O pins are likewise wired but ignored.
*/
};
static
irqreturn_t
dm365evm_keys_irq
(
int
irq
,
void
*
_keys
)
{
struct
dm365evm_keys
*
keys
=
_keys
;
/* For simplicity we ignore INPUT_COUNT and just read
* events until the GPIO stops signaling data ready.
*/
while
(
gpio_get_value
(
MSP430_GPIO
)
==
0
)
{
static
u16
last_event
;
u16
event
;
int
keycode
;
int
i
;
/* Read low, then high bytes; reading the high byte
* removes an entry from the input buffer.
*/
event
=
i2c_smbus_read_word_data
(
keys
->
i2c
,
DM365EVM_MSP_INPUT_LOW
);
if
(
event
<
0
)
{
dev_dbg
(
&
keys
->
i2c
->
dev
,
"input err %d
\n
"
,
event
);
break
;
}
event
=
event
;
/* Press and release a button: two events, same code.
* Press and hold (autorepeat), then release: N events
* (N > 2), same code. For RC5 buttons the toggle bits
* distinguish (for example) "1-autorepeat" from "1 1";
* but PCB buttons don't support that bit.
*
* So we must synthesize release events. We do that by
* mapping events to a press/release event pair; then
* to avoid adding extra events, skip the second event
* of each pair.
*/
if
(
event
==
last_event
)
{
last_event
=
0
;
continue
;
}
last_event
=
event
;
/* ignore the RC5 toggle bit */
event
&=
~
0x0800
;
/* find the key, or leave it as unknown */
keycode
=
KEY_UNKNOWN
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dm365evm_keys
);
i
++
)
{
if
(
dm365evm_keys
[
i
].
event
!=
event
)
continue
;
keycode
=
dm365evm_keys
[
i
].
keycode
;
break
;
}
dev_dbg
(
&
keys
->
i2c
->
dev
,
"input event 0x%04x--> keycode %d
\n
"
,
event
,
keycode
);
/* report press + release */
input_report_key
(
keys
->
input
,
keycode
,
1
);
input_sync
(
keys
->
input
);
input_report_key
(
keys
->
input
,
keycode
,
0
);
input_sync
(
keys
->
input
);
}
return
IRQ_HANDLED
;
}
/*
* Since we talk to the MSP using I2C, we need to delegate all real
* IRQ handling work to some task context. We'll use an IRQ thread.
*/
static
irqreturn_t
dm365evm_keys_hardirq
(
int
irq
,
void
*
_keys
)
{
return
IRQ_WAKE_THREAD
;
}
static
int
dm365evm_setkeycode
(
struct
input_dev
*
dev
,
int
index
,
int
keycode
)
{
u16
old_keycode
;
unsigned
i
;
if
(((
unsigned
)
index
)
>=
ARRAY_SIZE
(
dm365evm_keys
))
return
-
EINVAL
;
old_keycode
=
dm365evm_keys
[
index
].
keycode
;
dm365evm_keys
[
index
].
keycode
=
keycode
;
set_bit
(
keycode
,
dev
->
keybit
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dm365evm_keys
);
i
++
)
{
if
(
dm365evm_keys
[
index
].
keycode
==
old_keycode
)
goto
done
;
}
clear_bit
(
old_keycode
,
dev
->
keybit
);
done:
return
0
;
}
static
int
dm365evm_getkeycode
(
struct
input_dev
*
dev
,
int
index
,
int
*
keycode
)
{
if
(((
unsigned
)
index
)
>=
ARRAY_SIZE
(
dm365evm_keys
))
return
-
EINVAL
;
return
dm365evm_keys
[
index
].
keycode
;
}
/*----------------------------------------------------------------------*/
static
int
__devinit
dm365evm_keys_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
dm365evm_keys
*
keys
;
struct
input_dev
*
input
;
int
status
;
int
i
;
status
=
gpio_request
(
MSP430_GPIO
,
id
->
name
);
if
(
status
<
0
)
return
status
;
status
=
gpio_direction_input
(
MSP430_GPIO
);
if
(
status
<
0
)
{
gpio_free
(
MSP430_GPIO
);
return
status
;
}
/* allocate instance struct and input dev */
keys
=
kzalloc
(
sizeof
*
keys
,
GFP_KERNEL
);
input
=
input_allocate_device
();
if
(
!
keys
||
!
input
)
{
status
=
-
ENOMEM
;
goto
fail1
;
}
keys
->
i2c
=
i2c
;
keys
->
input
=
input
;
input_set_drvdata
(
input
,
keys
);
input
->
name
=
"DM365 EVM Controls"
;
input
->
phys
=
"dm365evm/input0"
;
input
->
dev
.
parent
=
&
i2c
->
dev
;
input
->
id
.
bustype
=
BUS_I2C
;
input
->
id
.
product
=
0x0365
;
input
->
id
.
version
=
i2c_smbus_read_byte_data
(
i2c
,
DM365EVM_MSP_FIRMREV
);
input
->
evbit
[
0
]
=
BIT
(
EV_KEY
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dm365evm_keys
);
i
++
)
__set_bit
(
dm365evm_keys
[
i
].
keycode
,
input
->
keybit
);
input
->
setkeycode
=
dm365evm_setkeycode
;
input
->
getkeycode
=
dm365evm_getkeycode
;
/* FIXME: flush the event queue */
status
=
request_threaded_irq
(
gpio_to_irq
(
MSP430_GPIO
),
dm365evm_keys_hardirq
,
dm365evm_keys_irq
,
IRQF_TRIGGER_FALLING
,
id
->
name
,
keys
);
if
(
status
<
0
)
goto
fail1
;
/* register */
status
=
input_register_device
(
input
);
if
(
status
<
0
)
goto
fail2
;
i2c_set_clientdata
(
i2c
,
keys
);
return
0
;
fail2:
free_irq
(
gpio_to_irq
(
MSP430_GPIO
),
keys
);
fail1:
input_free_device
(
input
);
kfree
(
keys
);
gpio_free
(
MSP430_GPIO
);
dev_err
(
&
i2c
->
dev
,
"can't register, err %d
\n
"
,
status
);
return
status
;
}
static
int
__devexit
dm365evm_keys_remove
(
struct
i2c_client
*
i2c
)
{
struct
dm365evm_keys
*
keys
=
i2c_get_clientdata
(
i2c
);
free_irq
(
gpio_to_irq
(
MSP430_GPIO
),
keys
);
input_unregister_device
(
keys
->
input
);
kfree
(
keys
);
gpio_free
(
MSP430_GPIO
);
return
0
;
}
/* REVISIT: add suspend/resume when DaVinci supports it. The IRQ should
* be able to wake up the system. When device_may_wakeup(&i2c->dev), call
* enable_irq_wake() on suspend, and disable_irq_wake() on resume.
*/
static
const
struct
i2c_device_id
ids
[]
=
{
{
.
name
=
"dm365evm_keys"
,
},
{
},
};
MODULE_DEVICE_TABLE
(
i2c
,
ids
);
static
struct
i2c_driver
dm365evm_keys_driver
=
{
.
driver
.
name
=
"dm365evm_keys"
,
.
id_table
=
ids
,
.
probe
=
dm365evm_keys_probe
,
.
remove
=
__devexit_p
(
dm365evm_keys_remove
),
};
static
int
__init
dm365evm_keys_init
(
void
)
{
return
i2c_add_driver
(
&
dm365evm_keys_driver
);
}
module_init
(
dm365evm_keys_init
);
static
void
__exit
dm365evm_keys_exit
(
void
)
{
i2c_del_driver
(
&
dm365evm_keys_driver
);
}
module_exit
(
dm365evm_keys_exit
);
MODULE_LICENSE
(
"GPL"
);
drivers/video/Kconfig
View file @
ca3e7676
...
@@ -1970,6 +1970,21 @@ config FB_IBM_GXT4500
...
@@ -1970,6 +1970,21 @@ config FB_IBM_GXT4500
Say Y here to enable support for the IBM GXT4500P display
Say Y here to enable support for the IBM GXT4500P display
adaptor, found on some IBM System P (pSeries) machines.
adaptor, found on some IBM System P (pSeries) machines.
config FB_DAVINCI
bool "Davinci Framebuffer support"
depends on FB && ARCH_DAVINCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
This is the frame buffer device driver for the DaVinci video
hardware found on the TI DaVinci EVM. If
unsure, say N.
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
config FB_PS3
config FB_PS3
tristate "PS3 GPU framebuffer driver"
tristate "PS3 GPU framebuffer driver"
depends on FB && PS3_PS3AV
depends on FB && PS3_PS3AV
...
...
drivers/video/Makefile
View file @
ca3e7676
...
@@ -139,6 +139,7 @@ obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
...
@@ -139,6 +139,7 @@ obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
obj-$(CONFIG_FB_BFIN_T350MCQB)
+=
bfin-t350mcqb-fb.o
obj-$(CONFIG_FB_BFIN_T350MCQB)
+=
bfin-t350mcqb-fb.o
obj-$(CONFIG_FB_MX3)
+=
mx3fb.o
obj-$(CONFIG_FB_MX3)
+=
mx3fb.o
obj-$(CONFIG_FB_DA8XX)
+=
da8xx-fb.o
obj-$(CONFIG_FB_DA8XX)
+=
da8xx-fb.o
obj-$(CONFIG_FB_DAVINCI)
+=
davincifb.o
# the test framebuffer is last
# the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL)
+=
vfb.o
obj-$(CONFIG_FB_VIRTUAL)
+=
vfb.o
...
...
drivers/video/davincifb.c
0 → 100644
View file @
ca3e7676
/*
* drivers/video/davincifb.c
*
* Framebuffer driver for Texas Instruments DaVinci display controller.
*
* Copyright (C) 2006 Texas Instruments, Inc.
* Rishi Bhattacharya <support@ti.com>
*
* Leveraged from the framebuffer driver for OMAP24xx
* written by Andy Lowe (source@mvista.com)
* Copyright (C) 2004 MontaVista Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <video/davincifb.h>
#include <asm/system.h>
#define MODULE_NAME "davincifb"
/* Output Format Selection */
#define MULTIPLE_BUFFERING 1
#ifdef MULTIPLE_BUFFERING
#define DOUBLE_BUF 2
#define TRIPLE_BUF 3
#else
#define DOUBLE_BUF 1
#define TRIPLE_BUF 1
#endif
/*
* display controller register I/O routines
*/
static
__inline__
u32
dispc_reg_in
(
u32
reg
)
{
return
ioread32
(
IO_ADDRESS
(
reg
));
}
static
__inline__
u32
dispc_reg_out
(
u32
reg
,
u32
val
)
{
iowrite32
(
val
,
IO_ADDRESS
(
reg
));
return
(
val
);
}
static
__inline__
u32
dispc_reg_merge
(
u32
reg
,
u32
val
,
u32
mask
)
{
u32
new_val
=
(
ioread32
(
IO_ADDRESS
(
reg
))
&
~
mask
)
|
(
val
&
mask
);
iowrite32
(
new_val
,
IO_ADDRESS
(
reg
));
return
(
new_val
);
}
/* There are 4 framebuffers, each represented by an fb_info and
* a dm_win_info structure */
#define OSD0_FBNAME "dm_osd0_fb"
#define OSD1_FBNAME "dm_osd1_fb"
#define VID0_FBNAME "dm_vid0_fb"
#define VID1_FBNAME "dm_vid1_fb"
/* usage: if (is_win(info->fix.id, OSD0)) ... */
#define is_win(name, x) ((strcmp(name, x ## _FBNAME) == 0) ? 1 : 0)
struct
dm_win_info
{
struct
fb_info
info
;
/* X and Y position */
unsigned
int
x
,
y
;
/* framebuffer area */
dma_addr_t
fb_base_phys
;
unsigned
long
fb_base
;
unsigned
long
fb_size
;
u32
pseudo_palette
[
17
];
/* flag to identify if framebuffer area is fixed already or not */
int
alloc_fb_mem
;
unsigned
long
sdram_address
;
struct
dm_info
*
dm
;
};
static
struct
dm_info
{
struct
dm_win_info
*
osd0
;
struct
dm_win_info
*
osd1
;
struct
dm_win_info
*
vid0
;
struct
dm_win_info
*
vid1
;
/* to map the registers */
dma_addr_t
mmio_base_phys
;
unsigned
long
mmio_base
;
unsigned
long
mmio_size
;
wait_queue_head_t
vsync_wait
;
unsigned
long
vsync_cnt
;
int
timeout
;
/* this is the function that configures the output device (NTSC/PAL/LCD)
* for the required output format (composite/s-video/component/rgb)
*/
void
(
*
output_device_config
)
(
int
on
);
struct
device
*
dev
;
}
dm_static
;
static
struct
dm_info
*
dm
=
&
dm_static
;
static
struct
fb_ops
davincifb_ops
;
#define BASEX 0x80
#define BASEY 0x12
#define DISP_XRES 720
#define DISP_YRES 480
#define DISP_MEMY 576
/* Random value chosen for now. Should be within the panel's supported range */
#define LCD_PANEL_CLOCK 180000
/* All window widths have to be rounded up to a multiple of 32 bytes */
/* The OSD0 window has to be always within VID0. Plus, since it is in RGB565
* mode, it _cannot_ overlap with VID1.
* For defaults, we are setting the OSD0 window to be displayed in the top
* left quadrant of the screen, and the VID1 in the bottom right quadrant.
* So the default 'xres' and 'yres' are set to half of the screen width and
* height respectively. Note however that the framebuffer size is allocated
* for the full screen size so the user can change the 'xres' and 'yres' by
* using the FBIOPUT_VSCREENINFO ioctl within the limits of the screen size.
*/
#define round_32(width) ((((width) + 31) / 32) * 32 )
#define OSD0_XRES round_32((DISP_XRES)*16/8) * 8/16
/* pixels */
#define OSD0_YRES DISP_YRES
#define OSD0_FB_PHY 0
#define OSD0_FB_SIZE (round_32((DISP_XRES)*16/8) * DISP_MEMY * DOUBLE_BUF)
/* 16 bpp, Double buffered */
static
struct
fb_var_screeninfo
osd0_default_var
=
{
.
xres
=
OSD0_XRES
,
.
yres
=
OSD0_YRES
,
.
xres_virtual
=
OSD0_XRES
,
.
yres_virtual
=
OSD0_YRES
*
DOUBLE_BUF
,
.
xoffset
=
0
,
.
yoffset
=
0
,
.
bits_per_pixel
=
16
,
.
grayscale
=
0
,
.
red
=
{
11
,
5
,
0
},
.
green
=
{
5
,
6
,
0
},
.
blue
=
{
0
,
5
,
0
},
.
transp
=
{
0
,
0
,
0
},
.
nonstd
=
0
,
.
activate
=
FB_ACTIVATE_NOW
,
.
height
=
-
1
,
.
width
=
-
1
,
.
accel_flags
=
0
,
.
pixclock
=
LCD_PANEL_CLOCK
,
/* picoseconds */
.
left_margin
=
40
,
/* pixclocks */
.
right_margin
=
4
,
/* pixclocks */
.
upper_margin
=
8
,
/* line clocks */
.
lower_margin
=
2
,
/* line clocks */
.
hsync_len
=
4
,
/* pixclocks */
.
vsync_len
=
2
,
/* line clocks */
.
sync
=
0
,
.
vmode
=
FB_VMODE_INTERLACED
,
};
/* Using the full screen for OSD1 by default */
#define OSD1_XRES round_32(DISP_XRES*4/8) * 8/4
/* pixels */
#define OSD1_YRES DISP_YRES
#define OSD1_FB_PHY 0
#define OSD1_FB_SIZE (round_32(DISP_XRES*4/8) * DISP_MEMY * DOUBLE_BUF)
static
struct
fb_var_screeninfo
osd1_default_var
=
{
.
xres
=
DISP_XRES
,
.
yres
=
OSD1_YRES
,
.
xres_virtual
=
OSD1_XRES
,
.
yres_virtual
=
OSD1_YRES
*
DOUBLE_BUF
,
.
xoffset
=
0
,
.
yoffset
=
0
,
.
bits_per_pixel
=
4
,
.
activate
=
FB_ACTIVATE_NOW
,
.
accel_flags
=
0
,
.
pixclock
=
LCD_PANEL_CLOCK
,
/* picoseconds */
.
vmode
=
FB_VMODE_INTERLACED
,
};
/* Using the full screen for OSD0 by default */
#define VID0_XRES round_32(DISP_XRES*16/8) * 8/16
/* pixels */
#define VID0_YRES DISP_YRES
#define VID0_FB_PHY 0
#define VID0_FB_SIZE (round_32(DISP_XRES*16/8) * DISP_MEMY * TRIPLE_BUF)
static
struct
fb_var_screeninfo
vid0_default_var
=
{
.
xres
=
VID0_XRES
,
.
yres
=
VID0_YRES
,
.
xres_virtual
=
VID0_XRES
,
.
yres_virtual
=
VID0_YRES
*
TRIPLE_BUF
,
.
xoffset
=
0
,
.
yoffset
=
0
,
.
bits_per_pixel
=
16
,
.
activate
=
FB_ACTIVATE_NOW
,
.
accel_flags
=
0
,
.
pixclock
=
LCD_PANEL_CLOCK
,
/* picoseconds */
.
vmode
=
FB_VMODE_INTERLACED
,
};
/* Using the bottom right quadrant of the screen screen for VID1 by default,
* but keeping the framebuffer allocated for the full screen, so the user can
* change the 'xres' and 'yres' later using the FBIOPUT_VSCREENINFO ioctl.
*/
#define VID1_BPP 16
/* Video1 can be in YUV or RGB888 format */
#define VID1_XRES round_32(DISP_XRES*16/8) * 8/16
/* pixels */
#define VID1_YRES DISP_YRES
#define VID1_FB_PHY 0
#define VID1_FB_SIZE (round_32(DISP_XRES*16/8) * DISP_MEMY * TRIPLE_BUF)
static
struct
fb_var_screeninfo
vid1_default_var
=
{
.
xres
=
VID1_XRES
,
.
yres
=
VID1_YRES
,
.
xres_virtual
=
VID1_XRES
,
.
yres_virtual
=
VID1_YRES
*
TRIPLE_BUF
,
.
xoffset
=
0
,
.
yoffset
=
0
,
.
bits_per_pixel
=
VID1_BPP
,
.
activate
=
FB_ACTIVATE_NOW
,
.
accel_flags
=
0
,
.
pixclock
=
LCD_PANEL_CLOCK
,
/* picoseconds */
.
vmode
=
FB_VMODE_INTERLACED
,
};
#define x_pos(w) ((w)->x)
#define y_pos(w) ((w)->y)
static
struct
dmparams_t
{
u8
output
;
u8
format
;
u8
windows
;
/* bitmap flag based on VID0, VID1, OSD0, OSD1
* definitions in header file */
u32
vid0_xres
;
u32
vid0_yres
;
u32
vid0_xpos
;
u32
vid0_ypos
;
u32
vid1_xres
;
u32
vid1_yres
;
u32
vid1_xpos
;
u32
vid1_ypos
;
u32
osd0_xres
;
u32
osd0_yres
;
u32
osd0_xpos
;
u32
osd0_ypos
;
u32
osd1_xres
;
u32
osd1_yres
;
u32
osd1_xpos
;
u32
osd1_ypos
;
}
dmparams
=
{
NTSC
,
/* output */
COMPOSITE
,
/* format */
(
1
<<
VID0
)
|
(
1
<<
VID1
)
|
(
1
<<
OSD0
)
|
(
1
<<
OSD1
),
/* windows registered */
720
,
480
,
0
,
0
,
/* vid0 size and position */
720
,
480
,
0
,
0
,
/* vid1 size and position */
720
,
480
,
0
,
0
,
/* osd0 size and position */
720
,
480
,
0
,
0
,
/* osd1 size and position */
};
/* Must do checks against the limits of the output device */
static
int
davincifb_venc_check_mode
(
const
struct
dm_win_info
*
w
,
const
struct
fb_var_screeninfo
*
var
)
{
return
0
;
}
static
void
set_sdram_params
(
char
*
id
,
u32
addr
,
u32
line_length
);
static
irqreturn_t
davincifb_isr
(
int
irq
,
void
*
arg
)
{
struct
dm_info
*
dm
=
(
struct
dm_info
*
)
arg
;
unsigned
long
addr
=
0
;
if
((
dispc_reg_in
(
VENC_VSTAT
)
&
0x00000010
)
==
0x10
)
{
xchg
(
&
addr
,
dm
->
osd0
->
sdram_address
);
if
(
addr
)
{
set_sdram_params
(
dm
->
osd0
->
info
.
fix
.
id
,
dm
->
osd0
->
sdram_address
,
dm
->
osd0
->
info
.
fix
.
line_length
);
dm
->
osd0
->
sdram_address
=
0
;
}
addr
=
0
;
xchg
(
&
addr
,
dm
->
osd1
->
sdram_address
);
if
(
addr
)
{
set_sdram_params
(
dm
->
osd1
->
info
.
fix
.
id
,
dm
->
osd1
->
sdram_address
,
dm
->
osd1
->
info
.
fix
.
line_length
);
dm
->
osd1
->
sdram_address
=
0
;
}
addr
=
0
;
xchg
(
&
addr
,
dm
->
vid0
->
sdram_address
);
if
(
addr
)
{
set_sdram_params
(
dm
->
vid0
->
info
.
fix
.
id
,
dm
->
vid0
->
sdram_address
,
dm
->
vid0
->
info
.
fix
.
line_length
);
dm
->
vid0
->
sdram_address
=
0
;
}
addr
=
0
;
xchg
(
&
addr
,
dm
->
vid1
->
sdram_address
);
if
(
addr
)
{
set_sdram_params
(
dm
->
vid1
->
info
.
fix
.
id
,
dm
->
vid1
->
sdram_address
,
dm
->
vid1
->
info
.
fix
.
line_length
);
dm
->
vid1
->
sdram_address
=
0
;
}
return
IRQ_HANDLED
;
}
else
{
++
dm
->
vsync_cnt
;
wake_up_interruptible
(
&
dm
->
vsync_wait
);
return
IRQ_HANDLED
;
}
return
IRQ_HANDLED
;
}
/* Wait for a vsync interrupt. This routine sleeps so it can only be called
* from process context.
*/
static
int
davincifb_wait_for_vsync
(
struct
dm_win_info
*
w
)
{
struct
dm_info
*
dm
=
w
->
dm
;
wait_queue_t
wq
;
unsigned
long
cnt
;
int
ret
;
init_waitqueue_entry
(
&
wq
,
current
);
cnt
=
dm
->
vsync_cnt
;
ret
=
wait_event_interruptible_timeout
(
dm
->
vsync_wait
,
cnt
!=
dm
->
vsync_cnt
,
dm
->
timeout
);
if
(
ret
<
0
)
return
(
ret
);
if
(
ret
==
0
)
return
(
-
ETIMEDOUT
);
return
(
0
);
}
/* Sets a uniform attribute value over a rectangular area on the attribute
* window. The attribute value (0 to 7) is passed through the fb_fillrect's
* color parameter.
*/
static
int
davincifb_set_attr_blend
(
struct
fb_fillrect
*
r
)
{
struct
fb_info
*
info
=
&
dm
->
osd1
->
info
;
struct
fb_var_screeninfo
*
var
=
&
dm
->
osd1
->
info
.
var
;
unsigned
long
start
=
0
;
u8
blend
;
u32
width_bytes
;
if
(
r
->
dx
+
r
->
width
>
var
->
xres_virtual
)
return
-
EINVAL
;
if
(
r
->
dy
+
r
->
height
>
var
->
yres_virtual
)
return
-
EINVAL
;
if
(
r
->
color
<
0
||
r
->
color
>
7
)
return
-
EINVAL
;
/* since bits_per_pixel = 4, this will truncate the width if it is
* not even. Similarly r->dx will be rounded down to an even pixel.
* ... Do we want to return an error otherwise?
*/
width_bytes
=
r
->
width
*
var
->
bits_per_pixel
/
8
;
start
=
dm
->
osd1
->
fb_base
+
r
->
dy
*
info
->
fix
.
line_length
+
r
->
dx
*
var
->
bits_per_pixel
/
8
;
blend
=
(((
u8
)
r
->
color
&
0xf
)
<<
4
)
|
((
u8
)
r
->
color
);
while
(
r
->
height
--
)
{
start
+=
info
->
fix
.
line_length
;
memset
((
void
*
)
start
,
blend
,
width_bytes
);
}
return
0
;
}
/* These position parameters are given through fb_var_screeninfo.
* xp = var.reserved[0], yp = var.reserved[1],
* xl = var.xres, yl = var.yres
*/
static
void
set_win_position
(
char
*
id
,
u32
xp
,
u32
yp
,
u32
xl
,
u32
yl
)
{
int
i
=
0
;
if
(
is_win
(
id
,
VID0
))
{
i
=
0
;
}
else
if
(
is_win
(
id
,
VID1
))
{
i
=
1
;
}
else
if
(
is_win
(
id
,
OSD0
))
{
i
=
2
;
}
else
if
(
is_win
(
id
,
OSD1
))
{
i
=
3
;
}
dispc_reg_out
(
OSD_WINXP
(
i
),
xp
);
dispc_reg_out
(
OSD_WINYP
(
i
),
yp
);
dispc_reg_out
(
OSD_WINXL
(
i
),
xl
);
dispc_reg_out
(
OSD_WINYL
(
i
),
yl
);
}
static
inline
void
get_win_position
(
struct
dm_win_info
*
w
,
u32
*
xp
,
u32
*
yp
,
u32
*
xl
,
u32
*
yl
)
{
struct
fb_var_screeninfo
*
v
=
&
w
->
info
.
var
;
*
xp
=
x_pos
(
w
);
*
yp
=
y_pos
(
w
);
*
xl
=
v
->
xres
;
*
yl
=
v
->
yres
;
}
/* Returns 1 if the windows overlap, 0 otherwise */
static
int
window_overlap
(
struct
dm_win_info
*
w
,
u32
xp
,
u32
yp
,
u32
xl
,
u32
yl
)
{
u32
_xp
=
0
,
_yp
=
0
,
_xl
=
0
,
_yl
=
0
;
#define OVERLAP(x1, y1, x2, y2, x3, y3, x4, y4) \
(!( ((x1)<(x3) && (x2)<(x3)) || ((x1)>(x4) && (x2)>(x4)) || \
((y1)<(y3) && (y2)<(y3)) || ((y1)>(y4) && (y2)>(y4)) ) \
)
if
(
!
w
)
return
(
0
);
get_win_position
(
w
,
&
_xp
,
&
_yp
,
&
_xl
,
&
_yl
);
return
(
OVERLAP
(
xp
,
yp
,
xp
+
xl
,
yp
+
yl
,
_xp
,
_yp
,
_xp
+
_xl
,
_yp
+
_yl
));
#undef OVERLAP
}
/* Returns 1 if the window parameters are within VID0, 0 otherwise */
static
int
within_vid0_limits
(
u32
xp
,
u32
yp
,
u32
xl
,
u32
yl
)
{
u32
vid0_xp
=
0
,
vid0_yp
=
0
,
vid0_xl
=
0
,
vid0_yl
=
0
;
if
(
!
dm
->
vid0
)
return
(
1
);
get_win_position
(
dm
->
vid0
,
&
vid0_xp
,
&
vid0_yp
,
&
vid0_xl
,
&
vid0_yl
);
if
((
xp
>=
vid0_xp
)
&&
(
yp
>=
vid0_yp
)
&&
(
xp
+
xl
<=
vid0_xp
+
vid0_xl
)
&&
(
yp
+
yl
<=
vid0_yp
+
vid0_yl
))
return
(
1
);
return
(
0
);
}
/* VID0 must be large enough to hold all other windows */
static
int
check_new_vid0_size
(
u32
xp0
,
u32
yp0
,
u32
xl0
,
u32
yl0
)
{
u32
_xp
=
0
,
_yp
=
0
,
_xl
=
0
,
_yl
=
0
;
#define WITHIN_LIMITS \
((_xp >= xp0) && (_yp >= yp0) && \
(_xp + _xl <= xp0 + xl0) && (_yp + _yl <= yp0 + yl0))
if
(
dm
->
osd0
)
{
get_win_position
(
dm
->
osd0
,
&
_xp
,
&
_yp
,
&
_xl
,
&
_yl
);
if
(
!
WITHIN_LIMITS
)
return
(
-
EINVAL
);
}
if
(
dm
->
osd1
)
{
get_win_position
(
dm
->
osd1
,
&
_xp
,
&
_yp
,
&
_xl
,
&
_yl
);
if
(
!
WITHIN_LIMITS
)
return
(
-
EINVAL
);
}
if
(
dm
->
vid1
)
{
get_win_position
(
dm
->
vid1
,
&
_xp
,
&
_yp
,
&
_xl
,
&
_yl
);
if
(
!
WITHIN_LIMITS
)
return
(
-
EINVAL
);
}
return
(
0
);
#undef WITHIN_LIMITS
}
/**
* davincifb_check_var - Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*
* Checks to see if the hardware supports the state requested by
* var passed in. This function does not alter the hardware state!!!
* This means the data stored in struct fb_info and struct xxx_par do
* not change. This includes the var inside of struct fb_info.
* Do NOT change these. This function can be called on its own if we
* intent to only test a mode and not actually set it.
* If the var passed in is slightly off by what the hardware can support
* then we alter the var PASSED in to what we can do.
*
* Returns negative errno on error, or zero on success.
*/
static
int
davincifb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
const
struct
dm_win_info
*
w
=
(
const
struct
dm_win_info
*
)
info
->
par
;
struct
fb_var_screeninfo
v
;
/* Rules:
* 1) Vid1, OSD0, OSD1 and Cursor must be fully contained inside of Vid0.
* 2) Vid0 and Vid1 are both set to accept YUV 4:2:2 (for now).
* 3) OSD window data is always packed into 32-bit words and left justified.
* 4) Each horizontal line of window data must be a multiple of 32 bytes.
* 32 bytes = 32 bytes / 2 bytes per pixel = 16 pixels.
* This implies that 'xres' must be a multiple of 32 bytes.
* 5) The offset registers hold the distance between the start of one line and
* the start of the next. This offset value must be a multiple of 32 bytes.
* This implies that 'xres_virtual' is also a multiple of 32 bytes. Note
* that 'xoffset' needn't be a multiple of 32 bytes.
* 6) OSD0 is set to accept RGB565.
* dispc_reg_merge(OSD_OSDWIN0ND, OSD_OSDWIN0ND_RGB0E, OSD_OSDWIN0ND_RGB0E)
* 7) OSD1 is set to be the attribute window.
* 8) Vid1 startX = Vid0 startX + N * 16 pixels (32 bytes)
* 9) Vid1 width = (16*N - 8) pixels
* 10) When one of the OSD windows is in RGB565, it cannot overlap with Vid1.
* 11) Vid1 start X position must be offset a multiple of 16 pixels from the
* left edge of Vid0.
*/
memcpy
(
&
v
,
var
,
sizeof
(
v
));
return
(
0
);
/* do board-specific checks on the var */
if
(
davincifb_venc_check_mode
(
w
,
&
v
))
return
(
-
EINVAL
);
if
(
v
.
xres_virtual
<
v
.
xres
||
v
.
yres_virtual
<
v
.
yres
)
return
(
-
EINVAL
);
if
(
v
.
xoffset
>
v
.
xres_virtual
-
v
.
xres
)
return
(
-
EINVAL
);
if
(
v
.
yoffset
>
v
.
yres_virtual
-
v
.
yres
)
return
(
-
EINVAL
);
if
((
v
.
xres
*
v
.
bits_per_pixel
/
8
)
%
32
||
(
v
.
xres_virtual
*
v
.
bits_per_pixel
/
8
)
%
32
)
/* Rules 4, 5 */
return
(
-
EINVAL
);
if
(
v
.
xres_virtual
*
v
.
yres_virtual
*
v
.
bits_per_pixel
/
8
>
w
->
fb_size
)
return
(
-
EINVAL
);
if
(
!
is_win
(
info
->
fix
.
id
,
VID0
))
{
/* Rule 1 */
if
(
!
within_vid0_limits
(
x_pos
(
w
),
y_pos
(
w
),
v
.
xres
,
v
.
yres
))
return
(
-
EINVAL
);
}
if
(
is_win
(
info
->
fix
.
id
,
OSD0
))
{
/* Rule 10 */
if
(
window_overlap
(
w
->
dm
->
vid1
,
x_pos
(
w
),
y_pos
(
w
),
v
.
xres
,
v
.
yres
))
return
(
-
EINVAL
);
/* Rule 5 */
v
.
bits_per_pixel
=
16
;
v
.
red
.
offset
=
11
;
v
.
green
.
offset
=
5
;
v
.
blue
.
offset
=
0
;
v
.
red
.
length
=
5
;
v
.
green
.
length
=
6
;
v
.
blue
.
length
=
5
;
v
.
transp
.
offset
=
v
.
transp
.
length
=
0
;
v
.
red
.
msb_right
=
v
.
green
.
msb_right
=
v
.
blue
.
msb_right
=
v
.
transp
.
msb_right
=
0
;
v
.
nonstd
=
0
;
v
.
accel_flags
=
0
;
}
else
if
(
is_win
(
info
->
fix
.
id
,
OSD1
))
{
v
.
bits_per_pixel
=
4
;
}
else
if
(
is_win
(
info
->
fix
.
id
,
VID0
))
{
if
(
check_new_vid0_size
(
x_pos
(
w
),
y_pos
(
w
),
v
.
xres
,
v
.
yres
))
return
(
-
EINVAL
);
v
.
bits_per_pixel
=
16
;
}
else
if
(
is_win
(
info
->
fix
.
id
,
VID1
))
{
/* Rule 11 */
if
((
x_pos
(
w
->
dm
->
vid0
)
-
x_pos
(
w
))
%
16
)
return
(
-
EINVAL
);
/* Video1 may be in YUV or RGB888 format */
if
((
v
.
bits_per_pixel
!=
16
)
&&
(
v
.
bits_per_pixel
!=
32
))
return
(
-
EINVAL
);
}
else
return
(
-
EINVAL
);
memcpy
(
var
,
&
v
,
sizeof
(
v
));
return
(
0
);
}
/* Interlaced = Frame mode, Non-interlaced = Field mode */
static
void
set_interlaced
(
char
*
id
,
unsigned
int
on
)
{
on
=
(
on
==
0
)
?
0
:
~
0
;
if
(
is_win
(
id
,
VID0
))
dispc_reg_merge
(
OSD_VIDWINMD
,
on
,
OSD_VIDWINMD_VFF0
);
else
if
(
is_win
(
id
,
VID1
))
dispc_reg_merge
(
OSD_VIDWINMD
,
on
,
OSD_VIDWINMD_VFF1
);
else
if
(
is_win
(
id
,
OSD0
))
dispc_reg_merge
(
OSD_OSDWIN0MD
,
on
,
OSD_OSDWIN0MD_OFF0
);
else
if
(
is_win
(
id
,
OSD1
))
dispc_reg_merge
(
OSD_OSDWIN1MD
,
on
,
OSD_OSDWIN1MD_OFF1
);
}
/* For zooming, we just have to set the start of framebuffer, the zoom factors
* and the display size. The hardware will then read only
* (display size / zoom factor) area of the framebuffer and zoom and
* display it. In the following function, we assume that the start of
* framebuffer and the display size parameters are set already.
*/
static
void
set_zoom
(
int
WinID
,
int
h_factor
,
int
v_factor
)
{
switch
(
WinID
)
{
case
0
:
//VID0
dispc_reg_merge
(
OSD_VIDWINMD
,
h_factor
<<
OSD_VIDWINMD_VHZ0_SHIFT
,
OSD_VIDWINMD_VHZ0
);
dispc_reg_merge
(
OSD_VIDWINMD
,
v_factor
<<
OSD_VIDWINMD_VVZ0_SHIFT
,
OSD_VIDWINMD_VVZ0
);
break
;
case
1
:
//VID1
dispc_reg_merge
(
OSD_VIDWINMD
,
h_factor
<<
OSD_VIDWINMD_VHZ1_SHIFT
,
OSD_VIDWINMD_VHZ1
);
dispc_reg_merge
(
OSD_VIDWINMD
,
v_factor
<<
OSD_VIDWINMD_VVZ1_SHIFT
,
OSD_VIDWINMD_VVZ1
);
break
;
case
2
:
//OSD0
dispc_reg_merge
(
OSD_OSDWIN0MD
,
h_factor
<<
OSD_OSDWIN0MD_OHZ0_SHIFT
,
OSD_OSDWIN0MD_OHZ0
);
dispc_reg_merge
(
OSD_OSDWIN0MD
,
v_factor
<<
OSD_OSDWIN0MD_OVZ0_SHIFT
,
OSD_OSDWIN0MD_OVZ0
);
break
;
case
3
:
dispc_reg_merge
(
OSD_OSDWIN1MD
,
h_factor
<<
OSD_OSDWIN1MD_OHZ1_SHIFT
,
OSD_OSDWIN1MD_OHZ1
);
dispc_reg_merge
(
OSD_OSDWIN1MD
,
v_factor
<<
OSD_OSDWIN1MD_OVZ1_SHIFT
,
OSD_OSDWIN1MD_OVZ1
);
break
;
}
}
/* Chooses the ROM CLUT for now. Can be extended later. */
static
void
set_bg_color
(
u8
clut
,
u8
color_offset
)
{
clut
=
0
;
/* 0 = ROM, 1 = RAM */
dispc_reg_merge
(
OSD_MODE
,
OSD_MODE_BCLUT
&
clut
,
OSD_MODE_BCLUT
);
dispc_reg_merge
(
OSD_MODE
,
color_offset
<<
OSD_MODE_CABG_SHIFT
,
OSD_MODE_CABG
);
}
static
void
set_sdram_params
(
char
*
id
,
u32
addr
,
u32
line_length
)
{
/* The parameters to be written to the registers should be in
* multiple of 32 bytes
*/
addr
=
addr
;
/* div by 32 */
line_length
=
line_length
/
32
;
if
(
is_win
(
id
,
VID0
))
{
dispc_reg_out
(
OSD_VIDWIN0ADR
,
addr
);
dispc_reg_out
(
OSD_VIDWIN0OFST
,
line_length
);
}
else
if
(
is_win
(
id
,
VID1
))
{
dispc_reg_out
(
OSD_VIDWIN1ADR
,
addr
);
dispc_reg_out
(
OSD_VIDWIN1OFST
,
line_length
);
}
else
if
(
is_win
(
id
,
OSD0
))
{
dispc_reg_out
(
OSD_OSDWIN0ADR
,
addr
);
dispc_reg_out
(
OSD_OSDWIN0OFST
,
line_length
);
}
else
if
(
is_win
(
id
,
OSD1
))
{
dispc_reg_out
(
OSD_OSDWIN1ADR
,
addr
);
dispc_reg_out
(
OSD_OSDWIN1OFST
,
line_length
);
}
}
static
void
set_win_enable
(
char
*
id
,
unsigned
int
on
)
{
on
=
(
on
==
0
)
?
0
:
~
0
;
if
(
is_win
(
id
,
VID0
))
/* Turning off VID0 use due to field inversion issue */
dispc_reg_merge
(
OSD_VIDWINMD
,
0
,
OSD_VIDWINMD_ACT0
);
else
if
(
is_win
(
id
,
VID1
))
dispc_reg_merge
(
OSD_VIDWINMD
,
on
,
OSD_VIDWINMD_ACT1
);
else
if
(
is_win
(
id
,
OSD0
))
dispc_reg_merge
(
OSD_OSDWIN0MD
,
on
,
OSD_OSDWIN0MD_OACT0
);
else
if
(
is_win
(
id
,
OSD1
))
{
/* The OACT1 bit is applicable only if OSD1 is not used as
* the attribute window
*/
if
(
!
(
dispc_reg_in
(
OSD_OSDWIN1MD
)
&
OSD_OSDWIN1MD_OASW
))
dispc_reg_merge
(
OSD_OSDWIN1MD
,
on
,
OSD_OSDWIN1MD_OACT1
);
}
}
static
void
set_win_mode
(
char
*
id
)
{
if
(
is_win
(
id
,
VID0
))
;
else
if
(
is_win
(
id
,
VID1
))
{
if
(
dm
->
vid1
->
info
.
var
.
bits_per_pixel
==
32
)
dispc_reg_merge
(
OSD_MISCCT
,
~
0
,
OSD_MISCCT_RGBWIN
|
OSD_MISCCT_RGBEN
);
}
else
if
(
is_win
(
id
,
OSD0
))
/* Set RGB565 mode */
dispc_reg_merge
(
OSD_OSDWIN0MD
,
OSD_OSDWIN0MD_RGB0E
,
OSD_OSDWIN0MD_RGB0E
);
else
if
(
is_win
(
id
,
OSD1
))
{
/* Set as attribute window */
dispc_reg_merge
(
OSD_OSDWIN1MD
,
OSD_OSDWIN1MD_OASW
,
OSD_OSDWIN1MD_OASW
);
}
}
/**
* davincifb_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*
* Using the fb_var_screeninfo in fb_info we set the resolution of the
* this particular framebuffer. This function alters the par AND the
* fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
* fb_info since we are using that data. This means we depend on the
* data in var inside fb_info to be supported by the hardware.
* davincifb_check_var is always called before dmfb_set_par to ensure this.
* Again if you can't can't the resolution you don't need this function.
*
*/
static
int
davincifb_set_par
(
struct
fb_info
*
info
)
{
struct
dm_win_info
*
w
=
(
struct
dm_win_info
*
)
info
->
par
;
struct
fb_var_screeninfo
*
v
=
&
info
->
var
;
u32
start
=
0
,
offset
=
0
;
info
->
fix
.
line_length
=
v
->
xres_virtual
*
v
->
bits_per_pixel
/
8
;
offset
=
v
->
yoffset
*
info
->
fix
.
line_length
+
v
->
xoffset
*
v
->
bits_per_pixel
/
8
;
start
=
(
u32
)
w
->
fb_base_phys
+
offset
;
set_sdram_params
(
info
->
fix
.
id
,
start
,
info
->
fix
.
line_length
);
set_interlaced
(
info
->
fix
.
id
,
1
);
set_win_position
(
info
->
fix
.
id
,
x_pos
(
w
),
y_pos
(
w
),
v
->
xres
,
v
->
yres
/
2
);
set_win_mode
(
info
->
fix
.
id
);
set_win_enable
(
info
->
fix
.
id
,
1
);
return
(
0
);
}
/**
* davincifb_ioctl - handler for private ioctls.
*/
static
int
davincifb_ioctl
(
struct
fb_info
*
info
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
dm_win_info
*
w
=
(
struct
dm_win_info
*
)
info
->
par
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
struct
fb_fillrect
rect
;
struct
zoom_params
zoom
;
long
std
=
0
;
switch
(
cmd
)
{
case
FBIO_WAITFORVSYNC
:
/* This ioctl accepts an integer argument to specify a
* display. We only support one display, so we will
* simply ignore the argument.
*/
return
(
davincifb_wait_for_vsync
(
w
));
break
;
case
FBIO_SETATTRIBUTE
:
if
(
copy_from_user
(
&
rect
,
argp
,
sizeof
(
rect
)))
return
-
EFAULT
;
return
(
davincifb_set_attr_blend
(
&
rect
));
break
;
case
FBIO_SETPOSX
:
if
(
arg
>=
0
&&
arg
<=
DISP_XRES
)
{
w
->
x
=
arg
;
davincifb_check_var
(
&
w
->
info
.
var
,
&
w
->
info
);
davincifb_set_par
(
&
w
->
info
);
return
0
;
}
else
return
-
EINVAL
;
break
;
case
FBIO_SETPOSY
:
if
(
arg
>=
0
&&
arg
<=
DISP_YRES
)
{
w
->
y
=
arg
;
davincifb_check_var
(
&
w
->
info
.
var
,
&
w
->
info
);
davincifb_set_par
(
&
w
->
info
);
return
0
;
}
else
return
-
EINVAL
;
break
;
case
FBIO_SETZOOM
:
if
(
copy_from_user
(
&
zoom
,
argp
,
sizeof
(
zoom
)))
return
-
EFAULT
;
if
((
zoom
.
zoom_h
==
2
)
||
(
zoom
.
zoom_h
==
0
)
||
(
zoom
.
zoom_h
==
1
)
||
(
zoom
.
zoom_v
==
2
)
||
(
zoom
.
zoom_v
==
0
)
||
(
zoom
.
zoom_v
==
1
))
{
set_zoom
(
zoom
.
window_id
,
zoom
.
zoom_h
,
zoom
.
zoom_v
);
return
0
;
}
else
{
return
-
EINVAL
;
}
break
;
case
FBIO_GETSTD
:
std
=
((
dmparams
.
output
<<
16
)
|
(
dmparams
.
format
));
//(NTSC <<16) | (COPOSITE);
if
(
copy_to_user
(
argp
,
&
std
,
sizeof
(
u_int32_t
)))
return
-
EFAULT
;
return
0
;
break
;
}
return
(
-
EINVAL
);
}
/**
* davincifb_setcolreg - Optional function. Sets a color register.
* @regno: Which register in the CLUT we are programming
* @red: The red value which can be up to 16 bits wide
* @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
* @transp: If supported the alpha value which can be up to 16 bits wide.
* @info: frame buffer info structure
*
* Set a single color register. The values supplied have a 16 bit
* magnitude which needs to be scaled in this function for the hardware.
* Things to take into consideration are how many color registers, if
* any, are supported with the current color visual. With truecolor mode
* no color palettes are supported. Here a psuedo palette is created
* which we store the value in pseudo_palette in struct fb_info. For
* pseudocolor mode we have a limited color palette. To deal with this
* we can program what color is displayed for a particular pixel value.
* DirectColor is similar in that we can program each color field. If
* we have a static colormap we don't need to implement this function.
*
* Returns negative errno on error, or zero on success.
*/
static
int
davincifb_setcolreg
(
unsigned
regno
,
unsigned
red
,
unsigned
green
,
unsigned
blue
,
unsigned
transp
,
struct
fb_info
*
info
)
{
/* only pseudo-palette (16 bpp) allowed */
if
(
regno
>=
16
)
/* maximum number of palette entries */
return
(
1
);
if
(
info
->
var
.
grayscale
)
{
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red
=
green
=
blue
=
(
red
*
77
+
green
*
151
+
blue
*
28
)
>>
8
;
}
/* Truecolor has hardware-independent 16-entry pseudo-palette */
if
(
info
->
fix
.
visual
==
FB_VISUAL_TRUECOLOR
)
{
u32
v
;
if
(
regno
>=
16
)
return
(
1
);
red
>>=
(
16
-
info
->
var
.
red
.
length
);
green
>>=
(
16
-
info
->
var
.
green
.
length
);
blue
>>=
(
16
-
info
->
var
.
blue
.
length
);
v
=
(
red
<<
info
->
var
.
red
.
offset
)
|
(
green
<<
info
->
var
.
green
.
offset
)
|
(
blue
<<
info
->
var
.
blue
.
offset
);
switch
(
info
->
var
.
bits_per_pixel
)
{
case
16
:
((
u16
*
)
(
info
->
pseudo_palette
))[
regno
]
=
v
;
break
;
default:
return
(
1
);
}
return
(
0
);
}
return
(
0
);
}
/**
* davincifb_pan_display - NOT a required function. Pans the display.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*
* Pan (or wrap, depending on the `vmode' field) the display using the
* `xoffset' and `yoffset' fields of the `var' structure.
* If the values don't fit, return -EINVAL.
*
* Returns negative errno on error, or zero on success.
*/
static
int
davincifb_pan_display
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
struct
dm_win_info
*
w
=
(
struct
dm_win_info
*
)
info
->
par
;
u32
start
=
0
,
offset
=
0
;
if
(
var
->
xoffset
>
var
->
xres_virtual
-
var
->
xres
)
return
(
-
EINVAL
);
if
(
var
->
yoffset
>
var
->
yres_virtual
-
var
->
yres
)
return
(
-
EINVAL
);
if
((
var
->
xres_virtual
*
var
->
bits_per_pixel
/
8
)
%
32
)
return
(
-
EINVAL
);
offset
=
var
->
yoffset
*
info
->
fix
.
line_length
+
var
->
xoffset
*
var
->
bits_per_pixel
/
8
;
start
=
(
u32
)
w
->
fb_base_phys
+
offset
;
if
((
dispc_reg_in
(
VENC_VSTAT
)
&
0x00000010
)
==
0x10
)
set_sdram_params
(
info
->
fix
.
id
,
start
,
info
->
fix
.
line_length
);
else
w
->
sdram_address
=
start
;
return
(
0
);
}
/**
* davincifb_blank - NOT a required function. Blanks the display.
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
*
* Blank the screen if blank_mode != 0, else unblank. Return 0 if
* blanking succeeded, != 0 if un-/blanking failed due to e.g. a
* video mode which doesn't support it. Implements VESA suspend
* and powerdown modes on hardware that supports disabling hsync/vsync:
* blank_mode == 2: suspend vsync
* blank_mode == 3: suspend hsync
* blank_mode == 4: powerdown
*
* Returns negative errno on error, or zero on success.
*
*/
static
int
davincifb_blank
(
int
blank_mode
,
struct
fb_info
*
info
)
{
return
0
;
}
static
int
parse_win_params
(
char
*
wp
,
int
*
xres
,
int
*
yres
,
int
*
xpos
,
int
*
ypos
)
{
char
*
s
;
if
((
s
=
strsep
(
&
wp
,
"x"
))
==
NULL
)
return
-
EINVAL
;
*
xres
=
simple_strtoul
(
s
,
NULL
,
0
);
if
((
s
=
strsep
(
&
wp
,
"@"
))
==
NULL
)
return
-
EINVAL
;
*
yres
=
simple_strtoul
(
s
,
NULL
,
0
);
if
((
s
=
strsep
(
&
wp
,
","
))
==
NULL
)
return
-
EINVAL
;
*
xpos
=
simple_strtoul
(
s
,
NULL
,
0
);
if
((
s
=
strsep
(
&
wp
,
":"
))
==
NULL
)
return
-
EINVAL
;
*
ypos
=
simple_strtoul
(
s
,
NULL
,
0
);
return
0
;
}
/*
* Pass boot-time options by adding the following string to the boot params:
* video=davincifb:[option[:option]]
* Valid options:
* output=[lcd|ntsc|pal]
* format=[composite|s-video|component|rgb]
* vid0=[off|MxN@X,Y]
* vid1=[off|MxN@X,Y]
* osd0=[off|MxN@X,Y]
* osd1=[off|MxN@X,Y]
* MxN specify the window resolution (displayed size)
* X,Y specify the window position
* M, N, X, Y are integers
* M, X should be multiples of 16
*/
#ifndef MODULE
int
__init
davincifb_setup
(
char
*
options
)
{
char
*
this_opt
;
u32
xres
,
yres
,
xpos
,
ypos
;
int
format_yres
=
480
;
pr_debug
(
"davincifb: Options
\"
%s
\"\n
"
,
options
);
if
(
!
options
||
!*
options
)
return
0
;
while
((
this_opt
=
strsep
(
&
options
,
":"
))
!=
NULL
)
{
if
(
!*
this_opt
)
continue
;
if
(
!
strncmp
(
this_opt
,
"output="
,
7
))
{
if
(
!
strncmp
(
this_opt
+
7
,
"lcd"
,
3
))
{
dmparams
.
output
=
LCD
;
dmparams
.
format
=
0
;
}
else
if
(
!
strncmp
(
this_opt
+
7
,
"ntsc"
,
4
))
dmparams
.
output
=
NTSC
;
else
if
(
!
strncmp
(
this_opt
+
7
,
"pal"
,
3
))
dmparams
.
output
=
PAL
;
}
else
if
(
!
strncmp
(
this_opt
,
"format="
,
7
))
{
if
(
dmparams
.
output
==
LCD
)
continue
;
if
(
!
strncmp
(
this_opt
+
7
,
"composite"
,
9
))
dmparams
.
format
=
COMPOSITE
;
else
if
(
!
strncmp
(
this_opt
+
7
,
"s-video"
,
7
))
dmparams
.
format
=
SVIDEO
;
else
if
(
!
strncmp
(
this_opt
+
7
,
"component"
,
9
))
dmparams
.
format
=
COMPONENT
;
else
if
(
!
strncmp
(
this_opt
+
7
,
"rgb"
,
3
))
dmparams
.
format
=
RGB
;
}
else
if
(
!
strncmp
(
this_opt
,
"vid0="
,
5
))
{
if
(
!
strncmp
(
this_opt
+
5
,
"off"
,
3
))
dmparams
.
windows
&=
~
(
1
<<
VID0
);
else
if
(
!
parse_win_params
(
this_opt
+
5
,
&
xres
,
&
yres
,
&
xpos
,
&
ypos
))
{
dmparams
.
vid0_xres
=
xres
;
dmparams
.
vid0_yres
=
yres
;
dmparams
.
vid0_xpos
=
xpos
;
dmparams
.
vid0_ypos
=
ypos
;
}
}
else
if
(
!
strncmp
(
this_opt
,
"vid1="
,
5
))
{
if
(
!
strncmp
(
this_opt
+
5
,
"off"
,
3
))
dmparams
.
windows
&=
~
(
1
<<
VID1
);
else
if
(
!
parse_win_params
(
this_opt
+
5
,
&
xres
,
&
yres
,
&
xpos
,
&
ypos
))
{
dmparams
.
vid1_xres
=
xres
;
dmparams
.
vid1_yres
=
yres
;
dmparams
.
vid1_xpos
=
xpos
;
dmparams
.
vid1_ypos
=
ypos
;
}
}
else
if
(
!
strncmp
(
this_opt
,
"osd0="
,
5
))
{
if
(
!
strncmp
(
this_opt
+
5
,
"off"
,
3
))
dmparams
.
windows
&=
~
(
1
<<
OSD0
);
else
if
(
!
parse_win_params
(
this_opt
+
5
,
&
xres
,
&
yres
,
&
xpos
,
&
ypos
))
{
dmparams
.
osd0_xres
=
xres
;
dmparams
.
osd0_yres
=
yres
;
dmparams
.
osd0_xpos
=
xpos
;
dmparams
.
osd0_ypos
=
ypos
;
}
}
else
if
(
!
strncmp
(
this_opt
,
"osd1="
,
5
))
{
if
(
!
strncmp
(
this_opt
+
5
,
"off"
,
3
))
dmparams
.
windows
&=
~
(
1
<<
OSD1
);
else
if
(
!
parse_win_params
(
this_opt
+
5
,
&
xres
,
&
yres
,
&
xpos
,
&
ypos
))
{
dmparams
.
osd1_xres
=
xres
;
dmparams
.
osd1_yres
=
yres
;
dmparams
.
osd1_xpos
=
xpos
;
dmparams
.
osd1_ypos
=
ypos
;
}
}
}
printk
(
KERN_INFO
"DaVinci: "
"Output on %s%s, Enabled windows: %s %s %s %s
\n
"
,
(
dmparams
.
output
==
LCD
)
?
"LCD"
:
(
dmparams
.
output
==
NTSC
)
?
"NTSC"
:
(
dmparams
.
output
==
PAL
)
?
"PAL"
:
"unknown device!"
,
(
dmparams
.
format
==
0
)
?
""
:
(
dmparams
.
format
==
COMPOSITE
)
?
" in COMPOSITE format"
:
(
dmparams
.
format
==
SVIDEO
)
?
" in SVIDEO format"
:
(
dmparams
.
format
==
COMPONENT
)
?
" in COMPONENT format"
:
(
dmparams
.
format
==
RGB
)
?
" in RGB format"
:
""
,
(
dmparams
.
windows
&
(
1
<<
VID0
))
?
"Video0"
:
""
,
(
dmparams
.
windows
&
(
1
<<
VID1
))
?
"Video1"
:
""
,
(
dmparams
.
windows
&
(
1
<<
OSD0
))
?
"OSD0"
:
""
,
(
dmparams
.
windows
&
(
1
<<
OSD1
))
?
"OSD1"
:
""
);
if
(
dmparams
.
output
==
NTSC
)
{
format_yres
=
480
;
}
else
if
(
dmparams
.
output
==
PAL
)
{
format_yres
=
576
;
}
else
{
printk
(
KERN_INFO
"DaVinci:invalid format..defaulting width to 480
\n
"
);
}
dmparams
.
osd0_yres
=
osd0_default_var
.
yres
=
format_yres
;
dmparams
.
osd1_yres
=
osd1_default_var
.
yres
=
format_yres
;
dmparams
.
vid0_yres
=
vid0_default_var
.
yres
=
format_yres
;
dmparams
.
vid1_yres
=
vid1_default_var
.
yres
=
format_yres
;
osd0_default_var
.
yres_virtual
=
format_yres
*
DOUBLE_BUF
;
osd1_default_var
.
yres_virtual
=
format_yres
*
DOUBLE_BUF
;
vid0_default_var
.
yres_virtual
=
format_yres
*
TRIPLE_BUF
;
vid1_default_var
.
yres_virtual
=
format_yres
*
TRIPLE_BUF
;
if
(
dmparams
.
windows
&
(
1
<<
VID0
))
printk
(
KERN_INFO
"Setting Video0 size %dx%d, "
"position (%d,%d)
\n
"
,
dmparams
.
vid0_xres
,
dmparams
.
vid0_yres
,
dmparams
.
vid0_xpos
,
dmparams
.
vid0_ypos
);
if
(
dmparams
.
windows
&
(
1
<<
VID1
))
printk
(
KERN_INFO
"Setting Video1 size %dx%d, "
"position (%d,%d)
\n
"
,
dmparams
.
vid1_xres
,
dmparams
.
vid1_yres
,
dmparams
.
vid1_xpos
,
dmparams
.
vid1_ypos
);
if
(
dmparams
.
windows
&
(
1
<<
OSD0
))
printk
(
KERN_INFO
"Setting OSD0 size %dx%d, "
"position (%d,%d)
\n
"
,
dmparams
.
osd0_xres
,
dmparams
.
osd0_yres
,
dmparams
.
osd0_xpos
,
dmparams
.
osd0_ypos
);
if
(
dmparams
.
windows
&
(
1
<<
OSD1
))
printk
(
KERN_INFO
"Setting OSD1 size %dx%d, "
"position (%d,%d)
\n
"
,
dmparams
.
osd1_xres
,
dmparams
.
osd1_yres
,
dmparams
.
osd1_xpos
,
dmparams
.
osd1_ypos
);
return
(
0
);
}
#endif
static
int
mem_release
(
struct
dm_win_info
*
w
)
{
if
(
!
w
->
alloc_fb_mem
)
{
iounmap
((
void
*
)
w
->
fb_base
);
release_mem_region
(
w
->
fb_base_phys
,
w
->
fb_size
);
}
else
dma_free_coherent
(
NULL
,
w
->
fb_size
,
(
void
*
)
w
->
fb_base
,
w
->
fb_base_phys
);
kfree
(
w
);
return
(
0
);
}
static
int
mem_alloc
(
struct
dm_win_info
**
win
,
dma_addr_t
fb_base_phys
,
unsigned
long
fb_size
,
char
*
fbname
)
{
struct
dm_win_info
*
w
;
struct
device
*
dev
=
dm
->
dev
;
w
=
kmalloc
(
sizeof
(
struct
dm_win_info
),
GFP_KERNEL
);
if
(
!
w
)
{
dev_err
(
dev
,
"%s: could not allocate memory
\n
"
,
fbname
);
return
(
-
ENOMEM
);
}
memset
(
w
,
0
,
sizeof
(
struct
dm_win_info
));
w
->
fb_base_phys
=
fb_base_phys
;
w
->
fb_size
=
fb_size
;
/* A null base address indicates that the framebuffer memory should be
* dynamically allocated.
*/
if
(
!
w
->
fb_base_phys
)
w
->
alloc_fb_mem
=
1
;
if
(
!
w
->
alloc_fb_mem
)
{
if
(
!
request_mem_region
(
w
->
fb_base_phys
,
w
->
fb_size
,
fbname
))
{
dev_err
(
dev
,
"%s: cannot reserve FB region
\n
"
,
fbname
);
goto
free_par
;
}
w
->
fb_base
=
(
unsigned
long
)
ioremap
(
w
->
fb_base_phys
,
w
->
fb_size
);
if
(
!
w
->
fb_base
)
{
dev_err
(
dev
,
"%s: cannot map framebuffer
\n
"
,
fbname
);
goto
release_fb
;
}
}
else
{
/* allocate coherent memory for the framebuffer */
w
->
fb_base
=
(
unsigned
long
)
dma_alloc_coherent
(
dev
,
w
->
fb_size
,
&
w
->
fb_base_phys
,
GFP_KERNEL
|
GFP_DMA
);
if
(
!
w
->
fb_base
)
{
dev_err
(
dev
,
"%s: cannot allocate framebuffer
\n
"
,
fbname
);
goto
free_par
;
}
dev_dbg
(
dev
,
"Framebuffer allocated at 0x%x "
"mapped to 0x%x, size %dk
\n
"
,
(
unsigned
)
w
->
fb_base_phys
,
(
unsigned
)
w
->
fb_base
,
(
unsigned
)
w
->
fb_size
/
1024
);
}
*
win
=
w
;
return
(
0
);
release_fb:
if
(
!
w
->
alloc_fb_mem
)
release_mem_region
(
w
->
fb_base_phys
,
w
->
fb_size
);
free_par:
kfree
(
w
);
return
(
-
ENOMEM
);
}
static
struct
fb_info
*
init_fb_info
(
struct
dm_win_info
*
w
,
struct
fb_var_screeninfo
*
var
,
char
*
id
)
{
struct
fb_info
*
info
=
&
(
w
->
info
);
struct
dm_info
*
dm
=
w
->
dm
;
/* initialize the fb_info structure */
info
->
flags
=
FBINFO_DEFAULT
;
info
->
fbops
=
&
davincifb_ops
;
info
->
screen_base
=
(
char
*
)(
w
->
fb_base
);
info
->
pseudo_palette
=
w
->
pseudo_palette
;
info
->
par
=
w
;
/* Initialize variable screeninfo.
* The variable screeninfo can be directly specified by the user
* via an ioctl.
*/
memcpy
(
&
info
->
var
,
var
,
sizeof
(
info
->
var
));
info
->
var
.
activate
=
FB_ACTIVATE_NOW
;
/* Initialize fixed screeninfo.
* The fixed screeninfo cannot be directly specified by the user, but
* it may change to reflect changes to the var info.
*/
strlcpy
(
info
->
fix
.
id
,
id
,
sizeof
(
info
->
fix
.
id
));
info
->
fix
.
smem_start
=
w
->
fb_base_phys
;
info
->
fix
.
line_length
=
(
info
->
var
.
xres_virtual
*
info
->
var
.
bits_per_pixel
)
/
8
;
info
->
fix
.
smem_len
=
w
->
fb_size
;
info
->
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fix
.
visual
=
(
info
->
var
.
bits_per_pixel
<=
8
)
?
FB_VISUAL_PSEUDOCOLOR
:
FB_VISUAL_TRUECOLOR
;
info
->
fix
.
xpanstep
=
0
;
info
->
fix
.
ypanstep
=
1
;
info
->
fix
.
ywrapstep
=
0
;
info
->
fix
.
type_aux
=
0
;
info
->
fix
.
mmio_start
=
dm
->
mmio_base_phys
;
info
->
fix
.
mmio_len
=
dm
->
mmio_size
;
info
->
fix
.
accel
=
FB_ACCEL_NONE
;
w
->
sdram_address
=
0
;
return
info
;
}
static
void
davincifb_ntsc_composite_config
(
int
on
)
{
if
(
on
)
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
/* Enable Composite output and start video encoder */
dispc_reg_out
(
VENC_VMOD
,
(
VENC_VMOD_VIE
|
VENC_VMOD_VENC
));
/* Set REC656 Mode */
dispc_reg_out
(
VENC_YCCCTL
,
0x1
);
/* Enable output mode and NTSC */
dispc_reg_out
(
VENC_VMOD
,
0x1003
);
/* Enable all DACs */
dispc_reg_out
(
VENC_DACTST
,
0
);
}
else
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
}
}
static
void
davincifb_ntsc_svideo_config
(
int
on
)
{
if
(
on
)
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
/* Enable Composite output and start video encoder */
dispc_reg_out
(
VENC_VMOD
,
(
VENC_VMOD_VIE
|
VENC_VMOD_VENC
));
/* Set REC656 Mode */
dispc_reg_out
(
VENC_YCCCTL
,
0x1
);
/* Enable output mode and NTSC */
dispc_reg_out
(
VENC_VMOD
,
0x1003
);
/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C */
dispc_reg_out
(
VENC_DACSEL
,
0x210
);
/* Enable all DACs */
dispc_reg_out
(
VENC_DACTST
,
0
);
}
else
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
}
}
static
void
davincifb_ntsc_component_config
(
int
on
)
{
if
(
on
)
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
/* Enable Composite output and start video encoder */
dispc_reg_out
(
VENC_VMOD
,
(
VENC_VMOD_VIE
|
VENC_VMOD_VENC
));
/* Set REC656 Mode */
dispc_reg_out
(
VENC_YCCCTL
,
0x1
);
/* Enable output mode and NTSC */
dispc_reg_out
(
VENC_VMOD
,
0x1003
);
/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr */
dispc_reg_out
(
VENC_DACSEL
,
0x543
);
/* Enable all DACs */
dispc_reg_out
(
VENC_DACTST
,
0
);
}
else
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
}
}
static
void
davincifb_pal_composite_config
(
int
on
)
{
if
(
on
)
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
/* Enable Composite output and start video encoder */
dispc_reg_out
(
VENC_VMOD
,
(
VENC_VMOD_VIE
|
VENC_VMOD_VENC
));
/* Set REC656 Mode */
dispc_reg_out
(
VENC_YCCCTL
,
0x1
);
/* Enable output mode and PAL */
dispc_reg_out
(
VENC_VMOD
,
0x1043
);
/* Enable all DACs */
dispc_reg_out
(
VENC_DACTST
,
0
);
}
else
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
}
}
static
void
davincifb_pal_svideo_config
(
int
on
)
{
if
(
on
)
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
/* Enable Composite output and start video encoder */
dispc_reg_out
(
VENC_VMOD
,
(
VENC_VMOD_VIE
|
VENC_VMOD_VENC
));
/* Set REC656 Mode */
dispc_reg_out
(
VENC_YCCCTL
,
0x1
);
/* Enable output mode and PAL */
dispc_reg_out
(
VENC_VMOD
,
0x1043
);
/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C */
dispc_reg_out
(
VENC_DACSEL
,
0x210
);
/* Enable all DACs */
dispc_reg_out
(
VENC_DACTST
,
0
);
}
else
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
}
}
static
void
davincifb_pal_component_config
(
int
on
)
{
if
(
on
)
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
/* Enable Composite output and start video encoder */
dispc_reg_out
(
VENC_VMOD
,
(
VENC_VMOD_VIE
|
VENC_VMOD_VENC
));
/* Set REC656 Mode */
dispc_reg_out
(
VENC_YCCCTL
,
0x1
);
/* Enable output mode and PAL */
dispc_reg_out
(
VENC_VMOD
,
0x1043
);
/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr */
dispc_reg_out
(
VENC_DACSEL
,
0x543
);
/* Enable all DACs */
dispc_reg_out
(
VENC_DACTST
,
0
);
}
else
{
/* Reset video encoder module */
dispc_reg_out
(
VENC_VMOD
,
0
);
}
}
static
inline
void
fix_default_var
(
struct
dm_win_info
*
w
,
u32
xres
,
u32
yres
,
u32
xpos
,
u32
ypos
,
int
n_buf
)
{
struct
fb_var_screeninfo
*
v
=
&
w
->
info
.
var
;
v
->
xres
=
xres
;
v
->
yres
=
yres
;
v
->
xres_virtual
=
v
->
xres
;
v
->
yres_virtual
=
v
->
yres
*
n_buf
;
x_pos
(
w
)
=
xpos
;
y_pos
(
w
)
=
ypos
;
}
/*
* Cleanup
*/
static
int
davincifb_remove
(
struct
platform_device
*
pdev
)
{
free_irq
(
IRQ_VENCINT
,
&
dm
);
/* Cleanup all framebuffers */
if
(
dm
->
osd0
)
{
unregister_framebuffer
(
&
dm
->
osd0
->
info
);
mem_release
(
dm
->
osd0
);
}
if
(
dm
->
osd1
)
{
unregister_framebuffer
(
&
dm
->
osd1
->
info
);
mem_release
(
dm
->
osd1
);
}
if
(
dm
->
vid0
)
{
unregister_framebuffer
(
&
dm
->
vid0
->
info
);
mem_release
(
dm
->
vid0
);
}
if
(
dm
->
vid1
)
{
unregister_framebuffer
(
&
dm
->
vid1
->
info
);
mem_release
(
dm
->
vid1
);
}
/* Turn OFF the output device */
dm
->
output_device_config
(
0
);
if
(
dm
->
mmio_base
)
iounmap
((
void
*
)
dm
->
mmio_base
);
release_mem_region
(
dm
->
mmio_base_phys
,
dm
->
mmio_size
);
return
0
;
}
/*
* Initialization
*/
static
int
davincifb_probe
(
struct
platform_device
*
pdev
)
{
struct
fb_info
*
info
;
if
(
dmparams
.
windows
==
0
)
return
0
;
/* user disabled all windows through bootargs */
dm
->
dev
=
&
pdev
->
dev
;
dm
->
mmio_base_phys
=
OSD_REG_BASE
;
dm
->
mmio_size
=
OSD_REG_SIZE
;
if
(
!
request_mem_region
(
dm
->
mmio_base_phys
,
dm
->
mmio_size
,
MODULE_NAME
))
{
dev_err
(
dm
->
dev
,
": cannot reserve MMIO region
\n
"
);
return
(
-
ENODEV
);
}
/* map the regions */
dm
->
mmio_base
=
(
unsigned
long
)
ioremap
(
dm
->
mmio_base_phys
,
dm
->
mmio_size
);
if
(
!
dm
->
mmio_base
)
{
dev_err
(
dm
->
dev
,
": cannot map MMIO
\n
"
);
goto
release_mmio
;
}
/* initialize the vsync wait queue */
init_waitqueue_head
(
&
dm
->
vsync_wait
);
dm
->
timeout
=
HZ
/
5
;
if
((
dmparams
.
output
==
NTSC
)
&&
(
dmparams
.
format
==
COMPOSITE
))
dm
->
output_device_config
=
davincifb_ntsc_composite_config
;
else
if
((
dmparams
.
output
==
NTSC
)
&&
(
dmparams
.
format
==
SVIDEO
))
dm
->
output_device_config
=
davincifb_ntsc_svideo_config
;
else
if
((
dmparams
.
output
==
NTSC
)
&&
(
dmparams
.
format
==
COMPONENT
))
dm
->
output_device_config
=
davincifb_ntsc_component_config
;
else
if
((
dmparams
.
output
==
PAL
)
&&
(
dmparams
.
format
==
COMPOSITE
))
dm
->
output_device_config
=
davincifb_pal_composite_config
;
else
if
((
dmparams
.
output
==
PAL
)
&&
(
dmparams
.
format
==
SVIDEO
))
dm
->
output_device_config
=
davincifb_pal_svideo_config
;
else
if
((
dmparams
.
output
==
PAL
)
&&
(
dmparams
.
format
==
COMPONENT
))
dm
->
output_device_config
=
davincifb_pal_component_config
;
/* Add support for other displays here */
else
{
printk
(
KERN_WARNING
"Unsupported output device!
\n
"
);
dm
->
output_device_config
=
NULL
;
}
printk
(
"Setting Up Clocks for DM420 OSD
\n
"
);
/* Initialize the VPSS Clock Control register */
dispc_reg_out
(
VPSS_CLKCTL
,
0x18
);
/* Set Base Pixel X and Base Pixel Y */
dispc_reg_out
(
OSD_BASEPX
,
BASEX
);
dispc_reg_out
(
OSD_BASEPY
,
BASEY
);
/* Reset OSD registers to default. */
dispc_reg_out
(
OSD_MODE
,
0
);
dispc_reg_out
(
OSD_OSDWIN0MD
,
0
);
/* Set blue background color */
set_bg_color
(
0
,
162
);
/* Field Inversion Workaround */
dispc_reg_out
(
OSD_MODE
,
0x200
);
/* Setup VID0 framebuffer */
if
(
!
(
dmparams
.
windows
&
(
1
<<
VID0
)))
{
printk
(
KERN_WARNING
"No video/osd windows will be enabled "
"because Video0 is disabled
\n
"
);
return
0
;
/* background will still be shown */
}
/* Setup VID0 framebuffer */
if
(
!
mem_alloc
(
&
dm
->
vid0
,
VID0_FB_PHY
,
VID0_FB_SIZE
,
VID0_FBNAME
))
{
dm
->
vid0
->
dm
=
dm
;
fix_default_var
(
dm
->
vid0
,
dmparams
.
vid0_xres
,
dmparams
.
vid0_yres
,
dmparams
.
vid0_xpos
,
dmparams
.
vid0_ypos
,
TRIPLE_BUF
);
info
=
init_fb_info
(
dm
->
vid0
,
&
vid0_default_var
,
VID0_FBNAME
);
if
(
davincifb_check_var
(
&
info
->
var
,
info
))
{
dev_err
(
dm
->
dev
,
": invalid default video mode
\n
"
);
goto
exit
;
}
memset
((
void
*
)
dm
->
vid0
->
fb_base
,
0x88
,
dm
->
vid0
->
fb_size
);
}
else
goto
exit
;
/* Setup OSD0 framebuffer */
if
((
dmparams
.
windows
&
(
1
<<
OSD0
))
&&
(
!
mem_alloc
(
&
dm
->
osd0
,
OSD0_FB_PHY
,
OSD0_FB_SIZE
,
OSD0_FBNAME
)))
{
dm
->
osd0
->
dm
=
dm
;
fix_default_var
(
dm
->
osd0
,
dmparams
.
osd0_xres
,
dmparams
.
osd0_yres
,
dmparams
.
osd0_xpos
,
dmparams
.
osd0_ypos
,
DOUBLE_BUF
);
info
=
init_fb_info
(
dm
->
osd0
,
&
osd0_default_var
,
OSD0_FBNAME
);
if
(
davincifb_check_var
(
&
info
->
var
,
info
))
{
dev_err
(
dm
->
dev
,
": invalid default video mode
\n
"
);
mem_release
(
dm
->
osd0
);
}
else
memset
((
void
*
)
dm
->
osd0
->
fb_base
,
0
,
dm
->
osd0
->
fb_size
);
}
/* Setup OSD1 framebuffer */
if
((
dmparams
.
windows
&
(
1
<<
OSD1
))
&&
(
!
mem_alloc
(
&
dm
->
osd1
,
OSD1_FB_PHY
,
OSD1_FB_SIZE
,
OSD1_FBNAME
)))
{
dm
->
osd1
->
dm
=
dm
;
fix_default_var
(
dm
->
osd1
,
dmparams
.
osd1_xres
,
dmparams
.
osd1_yres
,
dmparams
.
osd1_xpos
,
dmparams
.
osd1_ypos
,
DOUBLE_BUF
);
info
=
init_fb_info
(
dm
->
osd1
,
&
osd1_default_var
,
OSD1_FBNAME
);
if
(
davincifb_check_var
(
&
info
->
var
,
info
))
{
dev_err
(
dm
->
dev
,
": invalid default video mode
\n
"
);
mem_release
(
dm
->
osd1
);
}
else
/* Set blend factor to show OSD windows */
memset
((
void
*
)
dm
->
osd1
->
fb_base
,
0xff
,
dm
->
osd1
->
fb_size
);
}
/* Setup VID1 framebuffer */
if
((
dmparams
.
windows
&
(
1
<<
VID1
))
&&
(
!
mem_alloc
(
&
dm
->
vid1
,
VID1_FB_PHY
,
VID1_FB_SIZE
,
VID1_FBNAME
)))
{
dm
->
vid1
->
dm
=
dm
;
fix_default_var
(
dm
->
vid1
,
dmparams
.
vid1_xres
,
dmparams
.
vid1_yres
,
dmparams
.
vid1_xpos
,
dmparams
.
vid1_ypos
,
TRIPLE_BUF
);
info
=
init_fb_info
(
dm
->
vid1
,
&
vid1_default_var
,
VID1_FBNAME
);
if
(
davincifb_check_var
(
&
info
->
var
,
info
))
{
dev_err
(
dm
->
dev
,
VID1_FBNAME
": invalid default video mode
\n
"
);
mem_release
(
dm
->
vid1
);
}
else
memset
((
void
*
)
dm
->
vid1
->
fb_base
,
0x88
,
dm
->
vid1
->
fb_size
);
}
/* Register OSD0 framebuffer */
if
(
dm
->
osd0
)
{
info
=
&
dm
->
osd0
->
info
;
if
(
register_framebuffer
(
info
)
<
0
)
{
dev_err
(
dm
->
dev
,
OSD0_FBNAME
"Unable to register OSD0 framebuffer
\n
"
);
mem_release
(
dm
->
osd0
);
}
else
{
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
info
->
node
,
info
->
fix
.
id
);
davincifb_set_par
(
info
);
}
}
/* Register VID0 framebuffer */
info
=
&
dm
->
vid0
->
info
;
if
(
register_framebuffer
(
info
)
<
0
)
{
dev_err
(
dm
->
dev
,
VID0_FBNAME
"Unable to register VID0 framebuffer
\n
"
);
goto
exit
;
}
else
{
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
info
->
node
,
info
->
fix
.
id
);
davincifb_set_par
(
info
);
}
/* Register OSD1 framebuffer */
if
(
dm
->
osd1
)
{
info
=
&
dm
->
osd1
->
info
;
if
(
register_framebuffer
(
info
)
<
0
)
{
dev_err
(
dm
->
dev
,
OSD1_FBNAME
"Unable to register OSD1 framebuffer
\n
"
);
mem_release
(
dm
->
osd1
);
}
else
{
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
info
->
node
,
info
->
fix
.
id
);
davincifb_set_par
(
info
);
}
}
/* Register VID1 framebuffer */
if
(
dm
->
vid1
)
{
info
=
&
dm
->
vid1
->
info
;
if
(
register_framebuffer
(
info
)
<
0
)
{
mem_release
(
dm
->
vid1
);
dev_err
(
dm
->
dev
,
VID1_FBNAME
"Unable to register VID1 framebuffer
\n
"
);
mem_release
(
dm
->
vid1
);
}
else
{
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
info
->
node
,
info
->
fix
.
id
);
davincifb_set_par
(
info
);
}
}
/* install our interrupt service routine */
if
(
request_irq
(
IRQ_VENCINT
,
davincifb_isr
,
IRQF_SHARED
,
MODULE_NAME
,
dm
))
{
dev_err
(
dm
->
dev
,
MODULE_NAME
": could not install interrupt service routine
\n
"
);
goto
exit
;
}
/* Turn ON the output device */
dm
->
output_device_config
(
1
);
return
(
0
);
exit:
davincifb_remove
(
pdev
);
iounmap
((
void
*
)
dm
->
mmio_base
);
release_mmio:
release_mem_region
(
dm
->
mmio_base_phys
,
dm
->
mmio_size
);
return
(
-
ENODEV
);
}
/* ------------------------------------------------------------------------- */
/*
* Frame buffer operations
*/
static
struct
fb_ops
davincifb_ops
=
{
.
owner
=
THIS_MODULE
,
.
fb_check_var
=
davincifb_check_var
,
.
fb_set_par
=
davincifb_set_par
,
.
fb_setcolreg
=
davincifb_setcolreg
,
.
fb_blank
=
davincifb_blank
,
.
fb_pan_display
=
davincifb_pan_display
,
.
fb_fillrect
=
cfb_fillrect
,
.
fb_copyarea
=
cfb_copyarea
,
.
fb_imageblit
=
cfb_imageblit
,
.
fb_rotate
=
NULL
,
.
fb_sync
=
NULL
,
.
fb_ioctl
=
davincifb_ioctl
,
};
static
struct
platform_driver
davincifb_driver
=
{
.
probe
=
davincifb_probe
,
.
remove
=
davincifb_remove
,
.
driver
=
{
.
name
=
MODULE_NAME
,
.
owner
=
THIS_MODULE
,
},
};
/* Register both the driver and the device */
int
__init
davincifb_init
(
void
)
{
#ifndef MODULE
/* boot-line options */
/* handle options for "dm64xxfb" for backwards compatability */
char
*
option
;
char
*
names
[]
=
{
"davincifb"
,
"dm64xxfb"
};
int
i
,
num_names
=
2
,
done
=
0
;
for
(
i
=
0
;
i
<
num_names
&&
!
done
;
i
++
)
{
if
(
fb_get_options
(
names
[
i
],
&
option
))
{
printk
(
MODULE_NAME
": Disabled on command-line.
\n
"
);
return
-
ENODEV
;
}
else
if
(
option
)
{
davincifb_setup
(
option
);
done
=
1
;
}
}
#endif
/* Register the driver with LDM */
if
(
platform_driver_register
(
&
davincifb_driver
))
{
pr_debug
(
"failed to register omapfb driver
\n
"
);
return
-
ENODEV
;
}
return
0
;
}
static
void
__exit
davincifb_cleanup
(
void
)
{
platform_driver_unregister
(
&
davincifb_driver
);
}
module_init
(
davincifb_init
);
module_exit
(
davincifb_cleanup
);
MODULE_DESCRIPTION
(
"Framebuffer driver for TI DaVinci"
);
MODULE_AUTHOR
(
"Texas Instruments"
);
MODULE_LICENSE
(
"GPL"
);
include/video/davincifb.h
0 → 100644
View file @
ca3e7676
/*
* include/video/davincifb.h
*
* Framebuffer driver for Texas Instruments DM644x display controller.
*
* Copyright (C) 2006 Texas Instruments, Inc.
* Rishi Bhattacharya <support@ti.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef _DAVINCIFB_H_
#define _DAVINCIFB_H_
#include <mach/io.h>
/* Base registers */
#define VPBE_REG_BASE 0x01c72780
#define VENC_REG_BASE 0x01c72400
#define OSD_REG_BASE 0x01c72600
#define OSD_REG_SIZE 0x00000180
/* VPBE Global Registers */
#define VPBE_PID (VPBE_BASE + 0x0)
#define VPBE_PCR (VPBE_BASE + 0x4)
/* VPSS Clock Control Register */
#define VPSS_CLKCTL 0x01c40044
/* VPBE Video Encoder / Digital LCD Subsystem Registers (VENC) */
#define VENC_VMOD (VENC_REG_BASE + 0x00)
#define VENC_VIDCTL (VENC_REG_BASE + 0x04)
#define VENC_VDPRO (VENC_REG_BASE + 0x08)
#define VENC_SYNCCTL (VENC_REG_BASE + 0x0C)
#define VENC_HSPLS (VENC_REG_BASE + 0x10)
#define VENC_VSPLS (VENC_REG_BASE + 0x14)
#define VENC_HINT (VENC_REG_BASE + 0x18)
#define VENC_HSTART (VENC_REG_BASE + 0x1C)
#define VENC_HVALID (VENC_REG_BASE + 0x20)
#define VENC_VINT (VENC_REG_BASE + 0x24)
#define VENC_VSTART (VENC_REG_BASE + 0x28)
#define VENC_VVALID (VENC_REG_BASE + 0x2C)
#define VENC_HSDLY (VENC_REG_BASE + 0x30)
#define VENC_VSDLY (VENC_REG_BASE + 0x34)
#define VENC_YCCCTL (VENC_REG_BASE + 0x38)
#define VENC_RGBCTL (VENC_REG_BASE + 0x3C)
#define VENC_RGBCLP (VENC_REG_BASE + 0x40)
#define VENC_LINECTL (VENC_REG_BASE + 0x44)
#define VENC_CULLLINE (VENC_REG_BASE + 0x48)
#define VENC_LCDOUT (VENC_REG_BASE + 0x4C)
#define VENC_BRTS (VENC_REG_BASE + 0x50)
#define VENC_BRTW (VENC_REG_BASE + 0x54)
#define VENC_ACCTL (VENC_REG_BASE + 0x58)
#define VENC_PWMP (VENC_REG_BASE + 0x5C)
#define VENC_PWMW (VENC_REG_BASE + 0x60)
#define VENC_DCLKCTL (VENC_REG_BASE + 0x64)
#define VENC_DCLKPTN0 (VENC_REG_BASE + 0x68)
#define VENC_DCLKPTN1 (VENC_REG_BASE + 0x6C)
#define VENC_DCLKPTN2 (VENC_REG_BASE + 0x70)
#define VENC_DCLKPTN3 (VENC_REG_BASE + 0x74)
#define VENC_DCLKPTN0A (VENC_REG_BASE + 0x78)
#define VENC_DCLKPTN1A (VENC_REG_BASE + 0x7C)
#define VENC_DCLKPTN2A (VENC_REG_BASE + 0x80)
#define VENC_DCLKPTN3A (VENC_REG_BASE + 0x84)
#define VENC_DCLKHS (VENC_REG_BASE + 0x88)
#define VENC_DCLKHSA (VENC_REG_BASE + 0x8C)
#define VENC_DCLKHR (VENC_REG_BASE + 0x90)
#define VENC_DCLKVS (VENC_REG_BASE + 0x94)
#define VENC_DCLKVR (VENC_REG_BASE + 0x98)
#define VENC_CAPCTL (VENC_REG_BASE + 0x9C)
#define VENC_CAPDO (VENC_REG_BASE + 0xA0)
#define VENC_CAPDE (VENC_REG_BASE + 0xA4)
#define VENC_ATR0 (VENC_REG_BASE + 0xA8)
#define VENC_ATR1 (VENC_REG_BASE + 0xAC)
#define VENC_ATR2 (VENC_REG_BASE + 0xB0)
#define VENC_EPSON_LCDCTL (VENC_REG_BASE + 0xB4)
#define VENC_CASIO_LCDCTL (VENC_REG_BASE + 0xB4)
#define VENC_UDISP_LCDCT (VENC_REG_BASE + 0xB4)
#define VENC_STN_LCDCT (VENC_REG_BASE + 0xB4)
#define VENC_VSTAT (VENC_REG_BASE + 0xB8)
#define VENC_RAMADR (VENC_REG_BASE + 0xBC)
#define VENC_RAMPORT (VENC_REG_BASE + 0xC0)
#define VENC_DACTST (VENC_REG_BASE + 0xC4)
#define VENC_YCOLVL (VENC_REG_BASE + 0xC8)
#define VENC_SCPROG (VENC_REG_BASE + 0xCC)
#define VENC_CVBS (VENC_REG_BASE + 0xDC)
#define VENC_CMPNT (VENC_REG_BASE + 0xE0)
#define VENC_ETMG0 (VENC_REG_BASE + 0xE4)
#define VENC_ETMG1 (VENC_REG_BASE + 0xE8)
#define VENC_ETMG2 (VENC_REG_BASE + 0xEC)
#define VENC_ETMG3 (VENC_REG_BASE + 0xF0)
#define VENC_DACSEL (VENC_REG_BASE + 0xF4)
#define VENC_ARGBX0 (VENC_REG_BASE + 0x100)
#define VENC_ARGBX1 (VENC_REG_BASE + 0x104)
#define VENC_ARGBX2 (VENC_REG_BASE + 0x108)
#define VENC_ARGBX3 (VENC_REG_BASE + 0x10C)
#define VENC_ARGBX4 (VENC_REG_BASE + 0x110)
#define VENC_DRGBX0 (VENC_REG_BASE + 0x114)
#define VENC_DRGBX1 (VENC_REG_BASE + 0x118)
#define VENC_DRGBX2 (VENC_REG_BASE + 0x11C)
#define VENC_DRGBX3 (VENC_REG_BASE + 0x120)
#define VENC_DRGBX4 (VENC_REG_BASE + 0x124)
#define VENC_VSTARTA (VENC_REG_BASE + 0x128)
#define VENC_OSDCLK0 (VENC_REG_BASE + 0x12C)
#define VENC_OSDCLK1 (VENC_REG_BASE + 0x130)
#define VENC_HVLDCL0 (VENC_REG_BASE + 0x134)
#define VENC_HVLDCL1 (VENC_REG_BASE + 0x138)
#define VENC_OSDHAD (VENC_REG_BASE + 0x13C)
#define VID0 0
#define VID1 1
#define OSD0 3
#define OSD1 4
/* VPBE On-Screen Display Subsystem Registers (OSD) */
#define OSD_MODE (OSD_REG_BASE + 0x00)
#define OSD_VIDWINMD (OSD_REG_BASE + 0x04)
#define OSD_OSDWIN0MD (OSD_REG_BASE + 0x08)
#define OSD_OSDWIN1MD (OSD_REG_BASE + 0x0C)
#define OSD_OSDATRMD (OSD_REG_BASE + 0x0C)
#define OSD_RECTCUR (OSD_REG_BASE + 0x10)
#define OSD_WINOFST(i) (OSD_REG_BASE + 0x18 + (i)*0x4)
#define OSD_VIDWIN0OFST (OSD_REG_BASE + 0x18)
#define OSD_VIDWIN1OFST (OSD_REG_BASE + 0x1C)
#define OSD_OSDWIN0OFST (OSD_REG_BASE + 0x20)
#define OSD_OSDWIN1OFST (OSD_REG_BASE + 0x24)
#define OSD_WINADR(i) (OSD_REG_BASE + 0x2C + (i)*0x4)
#define OSD_VIDWIN0ADR (OSD_REG_BASE + 0x2C)
#define OSD_VIDWIN1ADR (OSD_REG_BASE + 0x30)
#define OSD_OSDWIN0ADR (OSD_REG_BASE + 0x38)
#define OSD_OSDWIN1ADR (OSD_REG_BASE + 0x3C)
#define OSD_BASEPX (OSD_REG_BASE + 0x40)
#define OSD_BASEPY (OSD_REG_BASE + 0x44)
#define OSD_WINXP(i) (OSD_REG_BASE + 0x48 + (i)*0x10)
#define OSD_WINYP(i) (OSD_REG_BASE + 0x4C + (i)*0x10)
#define OSD_WINXL(i) (OSD_REG_BASE + 0x50 + (i)*0x10)
#define OSD_WINYL(i) (OSD_REG_BASE + 0x54 + (i)*0x10)
#define OSD_VIDWIN0XP (OSD_REG_BASE + 0x48)
#define OSD_VIDWIN0YP (OSD_REG_BASE + 0x4C)
#define OSD_VIDWIN0XL (OSD_REG_BASE + 0x50)
#define OSD_VIDWIN0YL (OSD_REG_BASE + 0x54)
#define OSD_VIDWIN1XP (OSD_REG_BASE + 0x58)
#define OSD_VIDWIN1YP (OSD_REG_BASE + 0x5C)
#define OSD_VIDWIN1XL (OSD_REG_BASE + 0x60)
#define OSD_VIDWIN1YL (OSD_REG_BASE + 0x64)
#define OSD_OSDWIN0XP (OSD_REG_BASE + 0x68)
#define OSD_OSDWIN0YP (OSD_REG_BASE + 0x6C)
#define OSD_OSDWIN0XL (OSD_REG_BASE + 0x70)
#define OSD_OSDWIN0YL (OSD_REG_BASE + 0x74)
#define OSD_OSDWIN1XP (OSD_REG_BASE + 0x78)
#define OSD_OSDWIN1YP (OSD_REG_BASE + 0x7C)
#define OSD_OSDWIN1XL (OSD_REG_BASE + 0x80)
#define OSD_OSDWIN1YL (OSD_REG_BASE + 0x84)
#define OSD_CURXP (OSD_REG_BASE + 0x88)
#define OSD_CURYP (OSD_REG_BASE + 0x8C)
#define OSD_CURXL (OSD_REG_BASE + 0x90)
#define OSD_CURYL (OSD_REG_BASE + 0x94)
#define OSD_W0BMP01 (OSD_REG_BASE + 0xA0)
#define OSD_W0BMP23 (OSD_REG_BASE + 0xA4)
#define OSD_W0BMP45 (OSD_REG_BASE + 0xA8)
#define OSD_W0BMP67 (OSD_REG_BASE + 0xAC)
#define OSD_W0BMP89 (OSD_REG_BASE + 0xB0)
#define OSD_W0BMPAB (OSD_REG_BASE + 0xB4)
#define OSD_W0BMPCD (OSD_REG_BASE + 0xB8)
#define OSD_W0BMPEF (OSD_REG_BASE + 0xBC)
#define OSD_W1BMP0 (OSD_REG_BASE + 0xC0)
#define OSD_W1BMP2 (OSD_REG_BASE + 0xC4)
#define OSD_W1BMP4 (OSD_REG_BASE + 0xC8)
#define OSD_W1BMP6 (OSD_REG_BASE + 0xCC)
#define OSD_W1BMP8 (OSD_REG_BASE + 0xD0)
#define OSD_W1BMPA (OSD_REG_BASE + 0xD4)
#define OSD_W1BMPC (OSD_REG_BASE + 0xD8)
#define OSD_W1BMPE (OSD_REG_BASE + 0xDC)
#define OSD_TI_TES (OSD_REG_BASE + 0xE0)
#define OSD_MISCCT (OSD_REG_BASE + 0xE8)
#define OSD_CLUTRAMYC (OSD_REG_BASE + 0xEC)
#define OSD_CLUTRAMC (OSD_REG_BASE + 0xF0)
#define OSD_TRANSPVA (OSD_REG_BASE + 0xF0)
#define OSD_PPVWIN0AD (OSD_REG_BASE + 0xFC)
/* bit definitions */
#define VPBE_PCR_VENC_DIV (1 << 1)
#define VPBE_PCR_CLK_OFF (1 << 0)
#define VENC_VMOD_VDMD_SHIFT 12
#define VENC_VMOD_VDMD_YCBCR16 0
#define VENC_VMOD_VDMD_YCBCR8 1
#define VENC_VMOD_VDMD_RGB666 2
#define VENC_VMOD_VDMD_RGB8 3
#define VENC_VMOD_VDMD_EPSON 4
#define VENC_VMOD_VDMD_CASIO 5
#define VENC_VMOD_VDMD_UDISPQVGA 6
#define VENC_VMOD_VDMD_STNLCD 7
#define VENC_VMOD_VDMD (7 << 12)
#define VENC_VMOD_ITLCL (1 << 11)
#define VENC_VMOD_ITLC (1 << 10)
#define VENC_VMOD_NSIT (1 << 9)
#define VENC_VMOD_HDMD (1 << 8)
#define VENC_VMOD_TVTYP (3 << 6)
#define VENC_VMOD_SLAVE (1 << 5)
#define VENC_VMOD_VMD (1 << 4)
#define VENC_VMOD_BLNK (1 << 3)
#define VENC_VMOD_VIE (1 << 1)
#define VENC_VMOD_VENC (1 << 0)
/* other VENC registers' bit positions not defined yet */
#define OSD_MODE_CS (1 << 15)
#define OSD_MODE_OVRSZ (1 << 14)
#define OSD_MODE_OHRSZ (1 << 13)
#define OSD_MODE_EF (1 << 12)
#define OSD_MODE_VVRSZ (1 << 11)
#define OSD_MODE_VHRSZ (1 << 10)
#define OSD_MODE_FSINV (1 << 9)
#define OSD_MODE_BCLUT (1 << 8)
#define OSD_MODE_CABG (0xff << 0)
#define OSD_MODE_CABG_SHIFT 0
#define OSD_VIDWINMD_VFINV (1 << 15)
#define OSD_VIDWINMD_V1EFC (1 << 14)
#define OSD_VIDWINMD_VHZ1 (3 << 12)
#define OSD_VIDWINMD_VHZ1_SHIFT 12
#define OSD_VIDWINMD_VVZ1 (3 << 10)
#define OSD_VIDWINMD_VVZ1_SHIFT 10
#define OSD_VIDWINMD_VFF1 (1 << 9)
#define OSD_VIDWINMD_ACT1 (1 << 8)
#define OSD_VIDWINMD_V0EFC (1 << 6)
#define OSD_VIDWINMD_VHZ0 (3 << 4)
#define OSD_VIDWINMD_VHZ0_SHIFT 4
#define OSD_VIDWINMD_VVZ0 (3 << 2)
#define OSD_VIDWINMD_VVZ0_SHIFT 2
#define OSD_VIDWINMD_VFF0 (1 << 1)
#define OSD_VIDWINMD_ACT0 (1 << 0)
#define OSD_OSDWIN0MD_ATN0E (1 << 14)
#define OSD_OSDWIN0MD_RGB0E (1 << 13)
#define OSD_OSDWIN0MD_CLUTS0 (1 << 12)
#define OSD_OSDWIN0MD_OHZ0 (3 << 10)
#define OSD_OSDWIN0MD_OHZ0_SHIFT 10
#define OSD_OSDWIN0MD_OVZ0 (3 << 8)
#define OSD_OSDWIN0MD_OVZ0_SHIFT 8
#define OSD_OSDWIN0MD_BMW0 (3 << 6)
#define OSD_OSDWIN0MD_BMW0_SHIFT 6
#define OSD_OSDWIN0MD_BLND0 (3 << 3)
#define OSD_OSDWIN0MD_BLND0_SHIFT 3
#define OSD_OSDWIN0MD_TE0 (1 << 2)
#define OSD_OSDWIN0MD_OFF0 (1 << 1)
#define OSD_OSDWIN0MD_OACT0 (1 << 0)
#define OSD_OSDWIN1MD_OASW (1 << 15)
#define OSD_OSDWIN1MD_ATN1E (1 << 14)
#define OSD_OSDWIN1MD_RGB1E (1 << 13)
#define OSD_OSDWIN1MD_CLUTS1 (1 << 12)
#define OSD_OSDWIN1MD_OHZ1 (3 << 10)
#define OSD_OSDWIN1MD_OHZ1_SHIFT 10
#define OSD_OSDWIN1MD_OVZ1 (3 << 8)
#define OSD_OSDWIN1MD_OVZ1_SHIFT 8
#define OSD_OSDWIN1MD_BMW1 (3 << 6)
#define OSD_OSDWIN1MD_BMW1_SHIFT 6
#define OSD_OSDWIN1MD_BLND1 (3 << 3)
#define OSD_OSDWIN1MD_BLND1_SHIFT 3
#define OSD_OSDWIN1MD_TE1 (1 << 2)
#define OSD_OSDWIN1MD_OFF1 (1 << 1)
#define OSD_OSDWIN1MD_OACT1 (1 << 0)
#define OSD_OSDATRMD_OASW (1 << 15)
#define OSD_OSDATRMD_OHZA (3 << 10)
#define OSD_OSDATRMD_OHZA_SHIFT 10
#define OSD_OSDATRMD_OVZA (3 << 8)
#define OSD_OSDATRMD_OVZA_SHIFT 8
#define OSD_OSDATRMD_BLNKINT (3 << 6)
#define OSD_OSDATRMD_BLNKINT_SHIFT 6
#define OSD_OSDATRMD_OFFA (1 << 1)
#define OSD_OSDATRMD_BLNK (1 << 0)
#define OSD_RECTCUR_RCAD (0xff << 8)
#define OSD_RECTCUR_RCAD_SHIFT 8
#define OSD_RECTCUR_CLUTSR (1 << 7)
#define OSD_RECTCUR_RCHW (3 << 4)
#define OSD_RECTCUR_RCHW_SHIFT 4
#define OSD_RECTCUR_RCVW (3 << 1)
#define OSD_RECTCUR_RCVW_SHIFT 1
#define OSD_RECTCUR_RCACT (1 << 0)
#define OSD_VIDWIN0OFST_V0LO (0x1ff << 0)
#define OSD_VIDWIN0OFST_V0LO_SHIFT 0
#define OSD_VIDWIN1OFST_V1LO (0x1ff << 0)
#define OSD_VIDWIN1OFST_V1LO_SHIFT 0
#define OSD_OSDWIN0OFST_O0LO (0x1ff << 0)
#define OSD_OSDWIN0OFST_O0LO_SHIFT 0
#define OSD_OSDWIN1OFST_O1LO (0x1ff << 0)
#define OSD_OSDWIN1OFST_O1LO_SHIFT 0
#define OSD_BASEPX_BPX (0x3ff << 0)
#define OSD_BASEPX_BPX_SHIFT 0
#define OSD_BASEPY_BPY (0x1ff << 0)
#define OSD_BASEPY_BPY_SHIFT 0
#define OSD_VIDWIN0XP_V0X (0x3ff << 0)
#define OSD_VIDWIN0XP_V0X_SHIFT 0
#define OSD_VIDWIN0YP_V0Y (0x1ff << 0)
#define OSD_VIDWIN0YP_V0Y_SHIFT 0
#define OSD_VIDWIN0XL_V0W (0xfff << 0)
#define OSD_VIDWIN0XL_V0W_SHIFT 0
#define OSD_VIDWIN0YL_V0H (0x7ff << 0)
#define OSD_VIDWIN0YL_V0H_SHIFT 0
#define OSD_VIDWIN1XP_V1X (0x3ff << 0)
#define OSD_VIDWIN1XP_V1X_SHIFT 0
#define OSD_VIDWIN1YP_V1Y (0x1ff << 0)
#define OSD_VIDWIN1YP_V1Y_SHIFT 0
#define OSD_VIDWIN1XL_V1W (0xfff << 0)
#define OSD_VIDWIN1XL_V1W_SHIFT 0
#define OSD_VIDWIN1YL_V1H (0x7ff << 0)
#define OSD_VIDWIN1YL_V1H_SHIFT 0
#define OSD_OSDWIN0XP_W0X (0x3ff << 0)
#define OSD_OSDWIN0XP_W0X_SHIFT 0
#define OSD_OSDWIN0YP_W0Y (0x1ff << 0)
#define OSD_OSDWIN0YP_W0Y_SHIFT 0
#define OSD_OSDWIN0XL_W0W (0xfff << 0)
#define OSD_OSDWIN0XL_W0W_SHIFT 0
#define OSD_OSDWIN0YL_W0H (0x7ff << 0)
#define OSD_OSDWIN0YL_W0H_SHIFT 0
#define OSD_OSDWIN1XP_W1X (0x3ff << 0)
#define OSD_OSDWIN1XP_W1X_SHIFT 0
#define OSD_OSDWIN1YP_W1Y (0x1ff << 0)
#define OSD_OSDWIN1YP_W1Y_SHIFT 0
#define OSD_OSDWIN1XL_W1W (0xfff << 0)
#define OSD_OSDWIN1XL_W1W_SHIFT 0
#define OSD_OSDWIN1YL_W1H (0x7ff << 0)
#define OSD_OSDWIN1YL_W1H_SHIFT 0
#define OSD_CURXP_RCSX (0x3ff << 0)
#define OSD_CURXP_RCSX_SHIFT 0
#define OSD_CURYP_RCSY (0x1ff << 0)
#define OSD_CURYP_RCSY_SHIFT 0
#define OSD_CURYL_RCSH (0x7ff << 0)
#define OSD_CURYL_RCSH_SHIFT 0
#define OSD_W0BMP01_PAL01 (0xff << 8)
#define OSD_W0BMP01_PAL01_SHIFT 8
#define OSD_W0BMP01_PAL00 (0xff << 0)
#define OSD_W0BMP01_PAL00_SHIFT 0
#define OSD_W0BMP23_PAL03 (0xff << 8)
#define OSD_W0BMP23_PAL03_SHIFT 8
#define OSD_W0BMP23_PAL02 (0xff << 0)
#define OSD_W0BMP23_PAL02_SHIFT 0
#define OSD_W0BMP45_PAL05 (0xff << 8)
#define OSD_W0BMP45_PAL05_SHIFT 8
#define OSD_W0BMP45_PAL04 (0xff << 0)
#define OSD_W0BMP45_PAL04_SHIFT 0
#define OSD_W0BMP67_PAL07 (0xff << 8)
#define OSD_W0BMP67_PAL07_SHIFT 8
#define OSD_W0BMP67_PAL06 (0xff << 0)
#define OSD_W0BMP67_PAL06_SHIFT 0
#define OSD_W0BMP89_PAL09 (0xff << 8)
#define OSD_W0BMP89_PAL09_SHIFT 8
#define OSD_W0BMP89_PAL08 (0xff << 0)
#define OSD_W0BMP89_PAL08_SHIFT 0
#define OSD_W0BMPAB_PAL11 (0xff << 8)
#define OSD_W0BMPAB_PAL11_SHIFT 8
#define OSD_W0BMPAB_PAL10 (0xff << 0)
#define OSD_W0BMPAB_PAL10_SHIFT 0
#define OSD_W0BMPCD_PAL13 (0xff << 8)
#define OSD_W0BMPCD_PAL13_SHIFT 8
#define OSD_W0BMPCD_PAL12 (0xff << 0)
#define OSD_W0BMPCD_PAL12_SHIFT 0
#define OSD_W0BMPEF_PAL15 (0xff << 8)
#define OSD_W0BMPEF_PAL15_SHIFT 8
#define OSD_W0BMPEF_PAL14 (0xff << 0)
#define OSD_W0BMPEF_PAL14_SHIFT 0
#define OSD_W1BMP0_PAL01 (0xff << 8)
#define OSD_W1BMP0_PAL01_SHIFT 8
#define OSD_W1BMP0_PAL00 (0xff << 0)
#define OSD_W1BMP0_PAL00_SHIFT 0
#define OSD_W1BMP2_PAL03 (0xff << 8)
#define OSD_W1BMP2_PAL03_SHIFT 8
#define OSD_W1BMP2_PAL02 (0xff << 0)
#define OSD_W1BMP2_PAL02_SHIFT 0
#define OSD_W1BMP4_PAL05 (0xff << 8)
#define OSD_W1BMP4_PAL05_SHIFT 8
#define OSD_W1BMP4_PAL04 (0xff << 0)
#define OSD_W1BMP4_PAL04_SHIFT 0
#define OSD_W1BMP6_PAL07 (0xff << 8)
#define OSD_W1BMP6_PAL07_SHIFT 8
#define OSD_W1BMP6_PAL06 (0xff << 0)
#define OSD_W1BMP6_PAL06_SHIFT 0
#define OSD_W1BMP8_PAL09 (0xff << 8)
#define OSD_W1BMP8_PAL09_SHIFT 8
#define OSD_W1BMP8_PAL08 (0xff << 0)
#define OSD_W1BMP8_PAL08_SHIFT 0
#define OSD_W1BMPA_PAL11 (0xff << 8)
#define OSD_W1BMPA_PAL11_SHIFT 8
#define OSD_W1BMPA_PAL10 (0xff << 0)
#define OSD_W1BMPA_PAL10_SHIFT 0
#define OSD_W1BMPC_PAL13 (0xff << 8)
#define OSD_W1BMPC_PAL13_SHIFT 8
#define OSD_W1BMPC_PAL12 (0xff << 0)
#define OSD_W1BMPC_PAL12_SHIFT 0
#define OSD_W1BMPE_PAL15 (0xff << 8)
#define OSD_W1BMPE_PAL15_SHIFT 8
#define OSD_W1BMPE_PAL14 (0xff << 0)
#define OSD_W1BMPE_PAL14_SHIFT 0
#define OSD_MISCCT_RGBEN (1 << 7)
#define OSD_MISCCT_RGBWIN (1 << 6)
#define OSD_MISCCT_TMON (1 << 5)
#define OSD_MISCCT_RSEL (1 << 4)
#define OSD_MISCCT_CPBSY (1 << 3)
#define OSD_MISCCT_PPSW (1 << 2)
#define OSD_MISCCT_PPRV (1 << 1)
#define OSD_CLUTRAMY_Y (0xff << 8)
#define OSD_CLUTRAMY_Y_SHIFT 8
#define OSD_CLUTRAMY_CB (0xff << 0)
#define OSD_CLUTRAMY_CB_SHIFT 0
#define OSD_CLUTRAM_CR (0xff << 8)
#define OSD_CLUTRAM_CR_SHIFT 8
#define OSD_CLUTRAM_CADDR (0xff << 0)
#define OSD_CLUTRAM_CADDR_SHIFT 0
#define OSD_TRANSPVA_RGBTRANS (0xff << 0)
#define OSD_TRANSPVA_RGBTRANS_SHIFT 0
#define LCD 0
#define NTSC 1
#define PAL 2
#define COMPOSITE 1
#define SVIDEO 2
#define COMPONENT 3
#define RGB 4
/* define the custom FBIO_WAITFORVSYNC ioctl */
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t)
#define FBIO_SETATTRIBUTE _IOW('F', 0x21, struct fb_fillrect)
#define FBIO_SETPOSX _IOW('F', 0x22, u_int32_t)
#define FBIO_SETPOSY _IOW('F', 0x23, u_int32_t)
struct
zoom_params
{
u_int32_t
window_id
;
u_int32_t
zoom_h
;
u_int32_t
zoom_v
;
};
#define FBIO_SETZOOM _IOW('F', 0x24, struct zoom_params)
#define FBIO_GETSTD _IOR('F', 0x25, u_int32_t)
#endif
/* _DAVINCIFB_H_ */
sound/soc/davinci/davinci-sffsdr.c
View file @
ca3e7676
...
@@ -29,7 +29,7 @@
...
@@ -29,7 +29,7 @@
#include <asm/plat-sffsdr/sffsdr-fpga.h>
#include <asm/plat-sffsdr/sffsdr-fpga.h>
#endif
#endif
#include <mach/
mcb
sp.h>
#include <mach/
a
sp.h>
#include <mach/edma.h>
#include <mach/edma.h>
#include "../codecs/pcm3008.h"
#include "../codecs/pcm3008.h"
...
@@ -63,8 +63,13 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream,
...
@@ -63,8 +63,13 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream,
}
}
#endif
#endif
/* set cpu DAI configuration */
/* Set cpu DAI configuration:
ret
=
snd_soc_dai_set_fmt
(
cpu_dai
,
AUDIO_FORMAT
);
* CLKX and CLKR are the inputs for the Sample Rate Generator.
* FSX and FSR are outputs, driven by the sample Rate Generator. */
ret
=
snd_soc_dai_set_fmt
(
cpu_dai
,
SND_SOC_DAIFMT_RIGHT_J
|
SND_SOC_DAIFMT_CBM_CFS
|
SND_SOC_DAIFMT_IB_NF
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -115,15 +120,15 @@ static struct snd_soc_device sffsdr_snd_devdata = {
...
@@ -115,15 +120,15 @@ static struct snd_soc_device sffsdr_snd_devdata = {
static
struct
resource
sffsdr_snd_resources
[]
=
{
static
struct
resource
sffsdr_snd_resources
[]
=
{
{
{
.
start
=
DAVINCI_
MCBSP
_BASE
,
.
start
=
DAVINCI_
ASP0
_BASE
,
.
end
=
DAVINCI_
MCBSP
_BASE
+
SZ_8K
-
1
,
.
end
=
DAVINCI_
ASP0
_BASE
+
SZ_8K
-
1
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
},
},
};
};
static
struct
evm_snd_platform_data
sffsdr_snd_data
=
{
static
struct
evm_snd_platform_data
sffsdr_snd_data
=
{
.
tx_dma_ch
=
DAVINCI_DMA_
MCBSP
_TX
,
.
tx_dma_ch
=
DAVINCI_DMA_
ASP0
_TX
,
.
rx_dma_ch
=
DAVINCI_DMA_
MCBSP
_RX
,
.
rx_dma_ch
=
DAVINCI_DMA_
ASP0
_RX
,
};
};
static
struct
platform_device
*
sffsdr_snd_device
;
static
struct
platform_device
*
sffsdr_snd_device
;
...
...
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