[MSM] Backported a lot of stuff from 2.6.35 and 2.6.32.59 kernels, compiles and tested on device
This commit is contained in:
parent
bffda154f5
commit
48322595f9
@ -404,6 +404,7 @@ CONFIG_HAVE_MLOCKED_PAGE_BIT=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ALLOW_CPU_ALIGNMENT=y
|
||||
# CONFIG_UACCESS_WITH_MEMCPY is not set
|
||||
|
||||
#
|
||||
|
@ -382,11 +382,13 @@ ENDPROC(sys_clone_wrapper)
|
||||
|
||||
sys_sigreturn_wrapper:
|
||||
add r0, sp, #S_OFF
|
||||
mov why, #0 @ prevent syscall restart handling
|
||||
b sys_sigreturn
|
||||
ENDPROC(sys_sigreturn_wrapper)
|
||||
|
||||
sys_rt_sigreturn_wrapper:
|
||||
add r0, sp, #S_OFF
|
||||
mov why, #0 @ prevent syscall restart handling
|
||||
b sys_rt_sigreturn
|
||||
ENDPROC(sys_rt_sigreturn_wrapper)
|
||||
|
||||
|
@ -158,10 +158,10 @@ __secondary_data:
|
||||
* registers.
|
||||
*/
|
||||
__enable_mmu:
|
||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||
orr r0, r0, #CR_A
|
||||
#else
|
||||
#ifdef CONFIG_ALLOW_CPU_ALIGNMENT
|
||||
bic r0, r0, #CR_A
|
||||
#else
|
||||
orr r0, r0, #CR_A
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_DCACHE_DISABLE
|
||||
bic r0, r0, #CR_C
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
@ -62,6 +63,19 @@ struct clkctl_acpu_speed {
|
||||
unsigned axiclk_khz;
|
||||
};
|
||||
|
||||
static unsigned long max_axi_rate;
|
||||
|
||||
struct regulator {
|
||||
struct device *dev;
|
||||
struct list_head list;
|
||||
int uA_load;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
char *supply_name;
|
||||
struct device_attribute dev_attr;
|
||||
struct regulator_dev *rdev;
|
||||
};
|
||||
|
||||
/* clock sources */
|
||||
#define CLK_TCXO 0 /* 19.2 MHz */
|
||||
#define CLK_GLOBAL_PLL 1 /* 768 MHz */
|
||||
@ -76,135 +90,46 @@ struct clkctl_acpu_speed {
|
||||
#define SRC_PLL1 3 /* 768 MHz */
|
||||
|
||||
struct clkctl_acpu_speed acpu_freq_tbl[] = {
|
||||
#ifdef CONFIG_HTCLEO_UNDERVOLT_1000
|
||||
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 1000, 14000 },
|
||||
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 1000, 14000},
|
||||
{ 96000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 1000, 14000 },
|
||||
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 1000, 14000 },
|
||||
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 1000, 29000 },
|
||||
//{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 1000, 29000 },
|
||||
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 1000, 58000 },
|
||||
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 1000, 117000 },
|
||||
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1000, 117000 },
|
||||
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1025, 117000 },
|
||||
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1050, 117000 },
|
||||
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1050, 117000 },
|
||||
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1075, 117000 },
|
||||
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1100, 117000 },
|
||||
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1125, 117000 },
|
||||
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1150, 117000 },
|
||||
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1150, 128000 },
|
||||
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1175, 128000 },
|
||||
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1200, 128000 },
|
||||
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1200, 128000 },
|
||||
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1225, 128000 },
|
||||
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1225, 128000 },
|
||||
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1225, 128000 },
|
||||
#elif CONFIG_HTCLEO_UNDERVOLT_925
|
||||
// should work with most of HD2s
|
||||
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 925, 14000 },
|
||||
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 925, 14000 },
|
||||
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 925, 29000 },
|
||||
//{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 925, 29000 },
|
||||
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 950, 58000 },
|
||||
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 975, 117000 },
|
||||
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1000, 117000 },
|
||||
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1025, 117000 },
|
||||
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1050, 117000 },
|
||||
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1050, 117000 },
|
||||
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1075, 117000 },
|
||||
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1100, 117000 },
|
||||
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1125, 117000 },
|
||||
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1150, 117000 },
|
||||
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1150, 128000 },
|
||||
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1175, 128000 },
|
||||
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1200, 128000 },
|
||||
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1200, 128000 },
|
||||
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1225, 128000 },
|
||||
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1225, 128000 },
|
||||
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1225, 128000 },
|
||||
#elif CONFIG_HTCLEO_UNDERVOLT_800
|
||||
// not working yet
|
||||
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 850, 14000 },
|
||||
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 850, 14000 },
|
||||
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 850, 29000 },
|
||||
//{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 850, 29000 },
|
||||
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 850, 58000 },
|
||||
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 875, 117000 },
|
||||
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 900, 117000 },
|
||||
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 925, 117000 },
|
||||
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 950, 117000 },
|
||||
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 950, 117000 },
|
||||
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 975, 117000 },
|
||||
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1000, 117000 },
|
||||
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1025, 117000 },
|
||||
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1050, 117000 },
|
||||
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1125, 128000 },
|
||||
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1125, 128000 },
|
||||
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1150, 128000 },
|
||||
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1150, 128000 },
|
||||
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1175, 128000 },
|
||||
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1175, 128000 },
|
||||
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1200, 128000 },
|
||||
#else
|
||||
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 1050, 14000},
|
||||
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 1050, 14000 },
|
||||
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 1050, 29000 },
|
||||
/* Work arround for acpu resume hung, GPLL is turn off by arm9 */
|
||||
/*{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 1050, 29000 },*/
|
||||
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 1050, 58000 },
|
||||
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 1050, 117000 },
|
||||
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1050, 117000 },
|
||||
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1075, 117000 },
|
||||
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1100, 117000 },
|
||||
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1100, 117000 },
|
||||
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1125, 117000 },
|
||||
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1150, 117000 },
|
||||
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1175, 117000 },
|
||||
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1200, 117000 },
|
||||
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1200, 128000 },
|
||||
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1225, 128000 },
|
||||
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1250, 128000 },
|
||||
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1275, 128000 },
|
||||
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1300, 128000 },
|
||||
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1300, 128000 },
|
||||
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1300, 128000 },
|
||||
#endif
|
||||
#ifdef CONFIG_HTCLEO_OVERCLOCK
|
||||
#ifdef CONFIG_HTCLEO_UNDERVOLT_1000
|
||||
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1225, 128000 },
|
||||
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1250, 128000 },
|
||||
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1275, 128000 },
|
||||
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
|
||||
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
|
||||
#elif CONFIG_HTCLEO_UNDERVOLT_925
|
||||
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1225, 128000 },
|
||||
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1250, 128000 },
|
||||
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1275, 128000 },
|
||||
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
|
||||
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
|
||||
#elif CONFIG_HTCLEO_UNDERVOLT_800
|
||||
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1225, 128000 },
|
||||
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1250, 128000 },
|
||||
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1275, 128000 },
|
||||
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
|
||||
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
|
||||
#else
|
||||
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1300, 128000 },
|
||||
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1300, 128000 },
|
||||
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1300, 128000 },
|
||||
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1325, 128000 },
|
||||
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
|
||||
#endif
|
||||
/* Work arround for acpu resume hung, GPLL is turn off by arm9 */
|
||||
/*{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 1050, 29000 },*/
|
||||
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 1000, 58000 },
|
||||
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 1000, 117000 },
|
||||
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1000, 117000 },
|
||||
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1050, 117000 },
|
||||
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1050, 117000 },
|
||||
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1050, 117000 },
|
||||
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1075, 117000 },
|
||||
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1100, 117000 },
|
||||
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1125, 117000 },
|
||||
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1150, 117000 },
|
||||
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1150, 128000 },
|
||||
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1175, 128000 },
|
||||
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1225, 128000 },
|
||||
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1250, 128000 },
|
||||
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1300, 128000 },
|
||||
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1300, 128000 },
|
||||
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1300, 128000 },
|
||||
#ifdef CONFIG_HTCLEO_OVERCLOCK
|
||||
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1300, 128000 },
|
||||
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1300, 128000 },
|
||||
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1300, 128000 },
|
||||
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
|
||||
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
|
||||
#endif
|
||||
#ifdef CONFIG_HTCLEO_EXOVERCLOCK
|
||||
{ 1228800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x20, 0, 1325, 128000 },
|
||||
{ 1267200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x21, 0, 1350, 128000 },
|
||||
{ 1305600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x22, 0, 1350, 128000 },
|
||||
{ 1344000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x23, 0, 1350, 128000 },
|
||||
{ 1382400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x24, 0, 1350, 128000 },
|
||||
{ 1420800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x25, 0, 1350, 128000 },
|
||||
{ 1459200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x26, 0, 1350, 128000 },
|
||||
{ 1497600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x27, 0, 1350, 128000 },
|
||||
{ 1536000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x28, 0, 1350, 128000 },
|
||||
{ 1228800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x20, 0, 1325, 128000 },
|
||||
{ 1267200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x21, 0, 1350, 128000 },
|
||||
{ 1305600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x22, 0, 1350, 128000 },
|
||||
{ 1344000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x23, 0, 1350, 128000 },
|
||||
{ 1382400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x24, 0, 1350, 128000 },
|
||||
{ 1420800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x25, 0, 1350, 128000 },
|
||||
{ 1459200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x26, 0, 1350, 128000 },
|
||||
{ 1497600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x27, 0, 1350, 128000 },
|
||||
{ 1536000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x28, 0, 1350, 128000 },
|
||||
#endif
|
||||
{ 0 },
|
||||
};
|
||||
@ -231,11 +156,10 @@ static void __init acpuclk_init_cpufreq_table(void)
|
||||
freq_table[i].index = i;
|
||||
freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||
|
||||
/* Skip speeds we don't want */
|
||||
if ( acpu_freq_tbl[i].acpu_khz == 19200 ||
|
||||
//acpu_freq_tbl[i].acpu_khz == 128000 ||
|
||||
acpu_freq_tbl[i].acpu_khz == 256000)
|
||||
continue;
|
||||
/* Skip speeds using the global pll */
|
||||
if (acpu_freq_tbl[i].acpu_khz == 256000 ||
|
||||
acpu_freq_tbl[i].acpu_khz == 19200)
|
||||
continue;
|
||||
|
||||
vdd = acpu_freq_tbl[i].vdd;
|
||||
/* Allow mpll and the first scpll speeds */
|
||||
@ -269,6 +193,7 @@ struct clock_state {
|
||||
unsigned long wait_for_irq_khz;
|
||||
struct clk* clk_ebi1;
|
||||
struct regulator *regulator;
|
||||
int (*acpu_set_vdd) (int mvolts);
|
||||
};
|
||||
|
||||
static struct clock_state drv_state = { 0 };
|
||||
@ -345,11 +270,10 @@ static void scpll_set_freq(uint32_t lval)
|
||||
dmb();
|
||||
|
||||
/* wait for frequency switch to finish */
|
||||
while (readl(SCPLL_STATUS_ADDR) & 0x1)
|
||||
;
|
||||
while (readl(SCPLL_STATUS_ADDR) & 0x1);
|
||||
|
||||
/* completion bit is not reliable for SHOT switch */
|
||||
udelay(25);
|
||||
udelay(15);
|
||||
}
|
||||
|
||||
/* write the new L val and switch mode */
|
||||
@ -363,8 +287,7 @@ static void scpll_set_freq(uint32_t lval)
|
||||
dmb();
|
||||
|
||||
/* wait for frequency switch to finish */
|
||||
while (readl(SCPLL_STATUS_ADDR) & 0x1)
|
||||
;
|
||||
while (readl(SCPLL_STATUS_ADDR) & 0x1);
|
||||
}
|
||||
|
||||
/* this is still a bit weird... */
|
||||
@ -625,13 +548,20 @@ static void __init acpuclk_init(void)
|
||||
}
|
||||
drv_state.current_speed = speed;
|
||||
|
||||
for (speed = acpu_freq_tbl; speed->acpu_khz; speed++)
|
||||
for (speed = acpu_freq_tbl; speed->acpu_khz; speed++) {
|
||||
speed->lpj = cpufreq_scale(loops_per_jiffy,
|
||||
init_khz, speed->acpu_khz);
|
||||
max_axi_rate = speed->axiclk_khz * 1000;
|
||||
}
|
||||
|
||||
loops_per_jiffy = drv_state.current_speed->lpj;
|
||||
}
|
||||
|
||||
unsigned long acpuclk_get_max_axi_rate(void)
|
||||
{
|
||||
return max_axi_rate;
|
||||
}
|
||||
|
||||
unsigned long acpuclk_get_rate(void)
|
||||
{
|
||||
return drv_state.current_speed->acpu_khz;
|
||||
@ -674,6 +604,7 @@ void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
|
||||
drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
|
||||
drv_state.power_collapse_khz = clkdata->power_collapse_khz;
|
||||
drv_state.wait_for_irq_khz = clkdata->wait_for_irq_khz;
|
||||
drv_state.acpu_set_vdd = acpuclk_set_vdd_level;
|
||||
|
||||
if (clkdata->mpll_khz)
|
||||
acpu_mpll->acpu_khz = clkdata->mpll_khz;
|
||||
@ -708,7 +639,7 @@ ssize_t acpuclk_get_vdd_levels_str(char *buf)
|
||||
void acpuclk_set_vdd(unsigned acpu_khz, int vdd)
|
||||
{
|
||||
int i;
|
||||
vdd = vdd / 25 * 25; //! regulator only accepts multiples of 25 (mV)
|
||||
vdd = (vdd / HTCLEO_TPS65023_UV_STEP_MV) * HTCLEO_TPS65023_UV_STEP_MV;
|
||||
mutex_lock(&drv_state.lock);
|
||||
for (i = 0; acpu_freq_tbl[i].acpu_khz; i++)
|
||||
{
|
||||
@ -722,5 +653,16 @@ void acpuclk_set_vdd(unsigned acpu_khz, int vdd)
|
||||
}
|
||||
mutex_unlock(&drv_state.lock);
|
||||
}
|
||||
|
||||
unsigned int acpuclk_get_vdd_min(void)
|
||||
{
|
||||
return HTCLEO_TPS65023_MIN_UV_MV;
|
||||
}
|
||||
unsigned int acpuclk_get_vdd_max(void)
|
||||
{
|
||||
return HTCLEO_TPS65023_MAX_UV_MV;
|
||||
}
|
||||
unsigned int acpuclk_get_vdd_step(void)
|
||||
{
|
||||
return HTCLEO_TPS65023_UV_STEP_MV;
|
||||
}
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <asm/gpio.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/htc_headset_mgr.h>
|
||||
#include <mach/board-htcleo-audio.h>
|
||||
|
||||
#include "board-htcleo.h"
|
||||
#include "devices.h"
|
||||
|
@ -39,7 +39,6 @@
|
||||
|
||||
#define HTCLEO_DEFAULT_BACKLIGHT_BRIGHTNESS 255
|
||||
|
||||
|
||||
static struct led_trigger *htcleo_lcd_backlight;
|
||||
static int auto_bl_state=0;
|
||||
static DEFINE_MUTEX(htcleo_backlight_lock);
|
||||
|
@ -118,7 +118,7 @@ int lightsensor_read_value(uint32_t *val)
|
||||
}
|
||||
|
||||
*val = data[1] | (data[0] << 8);
|
||||
D("lsensor adc = %d\n", *val);
|
||||
D("lsensor adc = %u\n", *val); /* val is unsigned */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <mach/vreg.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board-htcleo-mmc.h>
|
||||
|
||||
#include "board-htcleo.h"
|
||||
#include "devices.h"
|
||||
@ -391,7 +392,7 @@ static int __init htcleommc_dbg_init(void)
|
||||
{
|
||||
struct dentry *dent;
|
||||
|
||||
if (!machine_is_htcleo() && !machine_is_htcleo())
|
||||
if (!machine_is_htcleo())
|
||||
return 0;
|
||||
|
||||
dent = debugfs_create_dir("htcleo_mmc_dbg", 0);
|
||||
|
@ -55,7 +55,9 @@
|
||||
#ifdef CONFIG_SERIAL_BCM_BT_LPM
|
||||
#include <mach/bcm_bt_lpm.h>
|
||||
#endif
|
||||
#ifdef CONFIG_PERFLOCK
|
||||
#include <mach/perflock.h>
|
||||
#endif
|
||||
#include <mach/htc_headset_mgr.h>
|
||||
#include <mach/htc_headset_gpio.h>
|
||||
|
||||
@ -395,10 +397,9 @@ static uint32_t flashlight_gpio_table[] =
|
||||
PCOM_GPIO_CFG(HTCLEO_GPIO_FLASHLIGHT_FLASH, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA),
|
||||
};
|
||||
|
||||
static int config_htcleo_flashlight_gpios(void)
|
||||
static void config_htcleo_flashlight_gpios(void)
|
||||
{
|
||||
config_gpio_table(flashlight_gpio_table, ARRAY_SIZE(flashlight_gpio_table));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct flashlight_platform_data htcleo_flashlight_data =
|
||||
@ -748,28 +749,6 @@ static struct platform_device qsd_device_spi = {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// KGSL (HW3D support)#include <linux/android_pmem.h>
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
static struct resource msm_kgsl_resources[] =
|
||||
{
|
||||
{
|
||||
.name = "kgsl_reg_memory",
|
||||
.start = MSM_GPU_REG_PHYS,
|
||||
.end = MSM_GPU_REG_PHYS + MSM_GPU_REG_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "kgsl_phys_memory",
|
||||
.start = MSM_GPU_PHYS_BASE,
|
||||
.end = MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = INT_GRAPHICS,
|
||||
.end = INT_GRAPHICS,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static int htcleo_kgsl_power_rail_mode(int follow_clk)
|
||||
{
|
||||
int mode = follow_clk ? 0 : 1;
|
||||
@ -786,16 +765,7 @@ static int htcleo_kgsl_power(bool on)
|
||||
return msm_proc_comm(cmd, &rail_id, 0);
|
||||
}
|
||||
|
||||
static struct platform_device msm_kgsl_device =
|
||||
{
|
||||
.name = "kgsl",
|
||||
.id = -1,
|
||||
.resource = msm_kgsl_resources,
|
||||
.num_resources = ARRAY_SIZE(msm_kgsl_resources),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_KGSL
|
||||
/* start kgsl */
|
||||
/* start kgsl-3d0 */
|
||||
static struct resource kgsl_3d0_resources[] = {
|
||||
{
|
||||
.name = KGSL_3D0_REG_MEMORY,
|
||||
@ -843,9 +813,7 @@ struct platform_device msm_kgsl_3d0 = {
|
||||
.platform_data = &kgsl_3d0_pdata,
|
||||
},
|
||||
};
|
||||
/* end kgsl */
|
||||
#endif
|
||||
|
||||
/* end kgsl-3d0 */
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Memory
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@ -897,7 +865,7 @@ static struct platform_device android_pmem_mdp_device = {
|
||||
|
||||
static struct platform_device android_pmem_adsp_device = {
|
||||
.name = "android_pmem",
|
||||
.id = 4,
|
||||
.id = 1, /* 4 */
|
||||
.dev = {
|
||||
.platform_data = &android_pmem_adsp_pdata,
|
||||
},
|
||||
@ -905,7 +873,7 @@ static struct platform_device android_pmem_adsp_device = {
|
||||
|
||||
static struct platform_device android_pmem_venc_device = {
|
||||
.name = "android_pmem",
|
||||
.id = 5,
|
||||
.id = 3, /* 5 */
|
||||
.dev = {
|
||||
.platform_data = &android_pmem_venc_pdata,
|
||||
},
|
||||
@ -1083,6 +1051,7 @@ static struct msm_acpu_clock_platform_data htcleo_clock_data = {
|
||||
// .wait_for_irq_khz = 19200, // TCXO
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PERFLOCK
|
||||
static unsigned htcleo_perf_acpu_table[] = {
|
||||
245000000,
|
||||
576000000,
|
||||
@ -1093,6 +1062,8 @@ static struct perflock_platform_data htcleo_perflock_data = {
|
||||
.perf_acpu_table = htcleo_perf_acpu_table,
|
||||
.table_size = ARRAY_SIZE(htcleo_perf_acpu_table),
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Reset
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@ -1139,7 +1110,9 @@ static void __init htcleo_init(void)
|
||||
|
||||
msm_acpu_clock_init(&htcleo_clock_data);
|
||||
|
||||
#ifdef CONFIG_PERFLOCK
|
||||
perflock_init(&htcleo_perflock_data);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MSM_SERIAL_DEBUGGER)
|
||||
msm_serial_debug_init(MSM_UART1_PHYS, INT_UART1,
|
||||
|
@ -178,7 +178,8 @@
|
||||
|
||||
/* Voltage driver */
|
||||
#define HTCLEO_TPS65023_MIN_UV_MV (800)
|
||||
#define HTCLEO_TPS65023_MAX_UV_MV (1350)
|
||||
#define HTCLEO_TPS65023_MAX_UV_MV (1375)
|
||||
#define HTCLEO_TPS65023_UV_STEP_MV (25)
|
||||
|
||||
/* LEDS */
|
||||
#define LED_RGB (1 << 0)
|
||||
@ -196,11 +197,12 @@ struct microp_led_platform_data {
|
||||
int num_leds;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int htcleo_pm_set_vreg(int enable, unsigned id);
|
||||
int __init htcleo_init_panel(void);
|
||||
int htcleo_is_nand_boot(void);
|
||||
unsigned htcleo_get_vbus_state(void);
|
||||
void config_camera_on_gpios(void);
|
||||
void config_camera_off_gpios(void);
|
||||
int is_valid_mac_address(char *mac);
|
||||
|
||||
#endif /* __ARCH_ARM_MACH_MSM_BOARD_HTCLEO_H */
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
//#define ENABLE_CLOCK_INFO 1
|
||||
|
||||
extern struct clk msm_clocks[];
|
||||
|
||||
static DEFINE_MUTEX(clocks_mutex);
|
||||
static DEFINE_SPINLOCK(clocks_lock);
|
||||
static LIST_HEAD(clocks);
|
||||
@ -233,8 +235,16 @@ struct mdns_clock_params msm_clock_freq_parameters[] = {
|
||||
MSM_CLOCK_REG(64000000,0x19, 0x60, 0x30, 0, 2, 4, 1, 245760000), /* BT, 4000000 (*16) */
|
||||
};
|
||||
|
||||
int status_set_grp_clk = 0;
|
||||
int i_set_grp_clk = 0;
|
||||
int control_set_grp_clk;
|
||||
|
||||
static void set_grp_clk( int on )
|
||||
{
|
||||
int i = 0;
|
||||
int status = 0;
|
||||
int control;
|
||||
|
||||
if ( on != 0 )
|
||||
{
|
||||
//axi_reset
|
||||
@ -274,8 +284,7 @@ static void set_grp_clk( int on )
|
||||
writel(readl(MSM_CLK_CTL_BASE) |0x8, MSM_CLK_CTL_BASE);
|
||||
//grp MD
|
||||
writel(readl(MSM_CLK_CTL_BASE+0x80) |0x1, MSM_CLK_CTL_BASE+0x80); //PRPH_WEB_NS_REG
|
||||
int i = 0;
|
||||
int status = 0;
|
||||
|
||||
while ( status == 0 && i < 100) {
|
||||
i++;
|
||||
status = readl(MSM_CLK_CTL_BASE+0x84) & 0x1;
|
||||
@ -297,7 +306,7 @@ static void set_grp_clk( int on )
|
||||
writel(readl(MSM_CLK_CTL_BASE+0x290) |0x4, MSM_CLK_CTL_BASE+0x290); //MSM_RAIL_CLAMP_IO
|
||||
writel( 0x11f, MSM_CLK_CTL_BASE+0x284); //VDD_GRP_GFS_CTL
|
||||
|
||||
int control = readl(MSM_CLK_CTL_BASE+0x288); //VDD_VDC_GFS_CTL
|
||||
control = readl(MSM_CLK_CTL_BASE+0x288); //VDD_VDC_GFS_CTL
|
||||
if ( control & 0x100 )
|
||||
writel(readl(MSM_CLK_CTL_BASE) &(~(0x8)), MSM_CLK_CTL_BASE);
|
||||
}
|
||||
@ -1291,5 +1300,18 @@ static int __init clock_late_init(void)
|
||||
//pr_info("reset imem_config\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(clock_late_init);
|
||||
|
||||
struct clk_ops clk_ops_pcom = {
|
||||
.enable = pc_clk_enable,
|
||||
.disable = pc_clk_disable,
|
||||
.auto_off = pc_clk_disable,
|
||||
// .reset = pc_clk_reset,
|
||||
.set_rate = pc_clk_set_rate,
|
||||
.set_min_rate = pc_clk_set_min_rate,
|
||||
.set_max_rate = pc_clk_set_max_rate,
|
||||
.set_flags = pc_clk_set_flags,
|
||||
.get_rate = pc_clk_get_rate,
|
||||
.is_enabled = pc_clk_is_enabled,
|
||||
// .round_rate = pc_clk_round_rate,
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <mach/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
@ -17,6 +17,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/earlysuspend.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -138,13 +138,14 @@ dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd,
|
||||
complete(&cmd->complete);
|
||||
}
|
||||
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int crci_mask, unsigned int cmdptr)
|
||||
{
|
||||
struct msm_dmov_exec_cmdptr_cmd cmd;
|
||||
|
||||
PRINT_FLOW("dmov_exec_cmdptr(%d, %x)\n", id, cmdptr);
|
||||
|
||||
cmd.dmov_cmd.cmdptr = cmdptr;
|
||||
cmd.dmov_cmd.crci_mask = crci_mask;
|
||||
cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func;
|
||||
cmd.dmov_cmd.execute_func = NULL;
|
||||
cmd.id = id;
|
||||
|
29
arch/arm/mach-msm/include/mach/board-htcleo-audio.h
Normal file
29
arch/arm/mach-msm/include/mach/board-htcleo-audio.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* board-htcleo-mmc.h
|
||||
*
|
||||
* Copyright (C) 2011 marc1706
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HTCLEO_AUDIO_H
|
||||
#define HTCLEO_AUDIO_H
|
||||
|
||||
void htcleo_headset_enable(int en);
|
||||
void htcleo_speaker_enable(int en);
|
||||
void htcleo_receiver_enable(int en);
|
||||
void htcleo_bt_sco_enable(int en);
|
||||
void htcleo_mic_enable(int en);
|
||||
void htcleo_analog_init(void);
|
||||
int htcleo_get_rx_vol(uint8_t hw, int level);
|
||||
void __init htcleo_audio_init(void);
|
||||
|
||||
#endif // HTCLEO_AUDIO_H
|
||||
|
@ -136,4 +136,14 @@ struct microp_i2c_client_data {
|
||||
int microp_i2c_read(uint8_t addr, uint8_t *data, int length);
|
||||
int microp_i2c_write(uint8_t addr, uint8_t *data, int length);
|
||||
int capella_cm3602_power(int pwr_device, uint8_t enable);
|
||||
int microp_read_gpo_status(uint16_t *status);
|
||||
int microp_gpo_enable(uint16_t gpo_mask);
|
||||
int microp_gpo_disable(uint16_t gpo_mask);
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
void microp_early_suspend(struct early_suspend *h);
|
||||
void microp_early_resume(struct early_suspend *h);
|
||||
#endif // CONFIG_HAS_EARLYSUSPEND
|
||||
|
||||
|
||||
#endif
|
||||
|
31
arch/arm/mach-msm/include/mach/board-htcleo-mmc.h
Normal file
31
arch/arm/mach-msm/include/mach/board-htcleo-mmc.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* board-htcleo-mmc.h
|
||||
*
|
||||
* Copyright (C) 2011 marc1706
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HTCLEO_MMC_H
|
||||
#define HTCLEO_MMC_H
|
||||
|
||||
static bool opt_disable_sdcard;
|
||||
static void (*wifi_status_cb)(int card_present, void *dev_id);
|
||||
static void *wifi_status_cb_devid;
|
||||
static int htcleo_wifi_power_state;
|
||||
static int htcleo_wifi_reset_state;
|
||||
|
||||
int htcleo_wifi_set_carddetect(int val);
|
||||
int htcleo_wifi_power(int on);
|
||||
int htcleo_wifi_reset(int on);
|
||||
int __init htcleo_init_mmc(unsigned debug_uart);
|
||||
|
||||
#endif // HTCLEO_MMC_H
|
||||
|
@ -178,6 +178,8 @@ enum {
|
||||
BOOTMODE_OFFMODE_CHARGING = 0x5,
|
||||
};
|
||||
|
||||
void msm_hsusb_set_vbus_state(int online);
|
||||
|
||||
#define MSM_MAX_DEC_CNT 14
|
||||
/* 7k target ADSP information */
|
||||
/* Bit 23:0, for codec identification like mp3, wav etc *
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS 16
|
||||
#define NUM_STAT_OUTPUT_BUFFERS 3
|
||||
#define NUM_AF_STAT_OUTPUT_BUFFERS 3
|
||||
#define max_control_command_size 150
|
||||
|
||||
enum msm_queue {
|
||||
MSM_CAM_Q_CTRL, /* control command or control command status */
|
||||
|
@ -51,4 +51,7 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate);
|
||||
int clk_reset(struct clk *clk, enum clk_reset_action action);
|
||||
|
||||
int clk_set_flags(struct clk *clk, unsigned long flags);
|
||||
|
||||
unsigned long acpuclk_get_max_axi_rate(void);
|
||||
|
||||
#endif
|
||||
|
47
arch/arm/mach-msm/include/mach/debug_mm.h
Normal file
47
arch/arm/mach-msm/include/mach/debug_mm.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MACH_MSM_DEBUG_MM_H_
|
||||
#define __ARCH_ARM_MACH_MSM_DEBUG_MM_H_
|
||||
|
||||
/* The below macro removes the directory path name and retains only the
|
||||
* file name to avoid long path names in log messages that comes as
|
||||
* part of __FILE__ to compiler.
|
||||
*/
|
||||
#define __MM_FILE__ strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/')+1) : \
|
||||
__FILE__
|
||||
|
||||
#define MM_DBG(fmt, args...) pr_debug("[%s] " fmt,\
|
||||
__func__, ##args)
|
||||
|
||||
#define MM_INFO(fmt, args...) pr_info("[%s:%s] " fmt,\
|
||||
__MM_FILE__, __func__, ##args)
|
||||
|
||||
#define MM_ERR(fmt, args...) pr_err("[%s:%s] " fmt,\
|
||||
__MM_FILE__, __func__, ##args)
|
||||
#endif /* __ARCH_ARM_MACH_MSM_DEBUG_MM_H_ */
|
@ -27,6 +27,7 @@ struct msm_dmov_errdata {
|
||||
struct msm_dmov_cmd {
|
||||
struct list_head list;
|
||||
unsigned int cmdptr;
|
||||
unsigned int crci_mask;
|
||||
void (*complete_func)(struct msm_dmov_cmd *cmd,
|
||||
unsigned int result,
|
||||
struct msm_dmov_errdata *err);
|
||||
@ -38,7 +39,7 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
|
||||
void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd);
|
||||
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
|
||||
void msm_dmov_flush(unsigned int id);
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int crci_mask, unsigned int cmdptr);
|
||||
|
||||
|
||||
|
||||
|
@ -311,6 +311,7 @@
|
||||
#define INT_MDDI_CLIENT INT_MDC
|
||||
#define INT_NAND_WR_ER_DONE INT_EBI2_WR_ER_DONE
|
||||
#define INT_NAND_OP_DONE INT_EBI2_OP_DONE
|
||||
#define INT_GRAPHICS INT_GRP_3D
|
||||
|
||||
#define NR_SIRC_IRQS 0
|
||||
|
||||
|
@ -27,10 +27,12 @@ struct mddi_info;
|
||||
#define MSM_MDP_OUT_IF_FMT_RGB888 2
|
||||
|
||||
/* mdp override operations */
|
||||
#define MSM_MDP_PANEL_IGNORE_PIXEL_DATA (1 << 0)
|
||||
#define MSM_MDP_PANEL_IGNORE_PIXEL_DATA (1 << 0)
|
||||
#define MSM_MDP_PANEL_FLIP_UD (1 << 1)
|
||||
#define MSM_MDP_PANEL_FLIP_LR (1 << 2)
|
||||
#define MSM_MDP4_MDDI_DMA_SWITCH (1 << 3)
|
||||
#define MSM_MDP_DMA_PACK_ALIGN_LSB (1 << 4)
|
||||
#define MSM_MDP_RGB_PANEL_SELF_REFRESH (1 << 5)
|
||||
|
||||
/* mddi type */
|
||||
#define MSM_MDP_MDDI_TYPE_I 0
|
||||
@ -190,6 +192,7 @@ struct msm_lcdc_panel_ops {
|
||||
int (*uninit)(struct msm_lcdc_panel_ops *);
|
||||
int (*blank)(struct msm_lcdc_panel_ops *);
|
||||
int (*unblank)(struct msm_lcdc_panel_ops *);
|
||||
int (*shutdown)(struct msm_lcdc_panel_ops *);
|
||||
};
|
||||
|
||||
struct msm_lcdc_platform_data {
|
||||
@ -211,6 +214,8 @@ struct msm_tvenc_platform_data {
|
||||
|
||||
struct mdp_blit_req;
|
||||
struct fb_info;
|
||||
struct mdp_overlay;
|
||||
struct msmfb_overlay_data;
|
||||
struct mdp_device {
|
||||
struct device dev;
|
||||
void (*dma)(struct mdp_device *mdp, uint32_t addr,
|
||||
@ -227,14 +232,17 @@ struct mdp_device {
|
||||
int (*overlay_unset)(struct mdp_device *mdp, struct fb_info *fb,
|
||||
int ndx);
|
||||
int (*overlay_play)(struct mdp_device *mdp, struct fb_info *fb,
|
||||
struct msmfb_overlay_data *req, struct file *p_src_file);
|
||||
struct msmfb_overlay_data *req, struct file **p_src_file);
|
||||
#endif
|
||||
void (*set_grp_disp)(struct mdp_device *mdp, uint32_t disp_id);
|
||||
void (*configure_dma)(struct mdp_device *mdp);
|
||||
int (*check_output_format)(struct mdp_device *mdp, int bpp);
|
||||
int (*set_output_format)(struct mdp_device *mdp, int bpp);
|
||||
void (*set_panel_size)(struct mdp_device *mdp, int width, int height);
|
||||
unsigned color_format;
|
||||
unsigned overrides;
|
||||
uint32_t width; /*panel width*/
|
||||
uint32_t height; /*panel height*/
|
||||
};
|
||||
|
||||
struct class_interface;
|
||||
|
@ -19,12 +19,14 @@
|
||||
|
||||
#define AUDIO_FLAG_READ 0
|
||||
#define AUDIO_FLAG_WRITE 1
|
||||
#define AUDIO_FLAG_INCALL_MIXED 2
|
||||
|
||||
struct audio_buffer {
|
||||
dma_addr_t phys;
|
||||
void *data;
|
||||
uint32_t size;
|
||||
uint32_t used; /* 1 = CPU is waiting for DSP to consume this buf */
|
||||
uint32_t actual_size; /* actual number of bytes read by DSP */
|
||||
};
|
||||
|
||||
struct audio_client {
|
||||
@ -79,8 +81,10 @@ struct audio_client *q6audio_open_mp3(uint32_t bufsz, uint32_t rate,
|
||||
|
||||
struct audio_client *q6fm_open(void);
|
||||
|
||||
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
|
||||
uint32_t flags, void *data, uint32_t acdb_id);
|
||||
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t samplerate,
|
||||
uint32_t channels, uint32_t bitrate,
|
||||
uint32_t stream_format, uint32_t flags,
|
||||
uint32_t acdb_id);
|
||||
|
||||
struct audio_client *q6audio_open_qcelp(uint32_t bufsz, uint32_t rate,
|
||||
void *data, uint32_t acdb_id);
|
||||
@ -102,7 +106,7 @@ int q6audio_set_tx_mute(int mute);
|
||||
int q6audio_reinit_acdb(char* filename);
|
||||
int q6audio_update_acdb(uint32_t id_src, uint32_t id_dst);
|
||||
int q6audio_set_rx_volume(int level);
|
||||
int q6audio_set_tx_volume(int level);
|
||||
int q6audio_set_tx_volume(int mute);
|
||||
int q6audio_set_stream_volume(struct audio_client *ac, int vol);
|
||||
int q6audio_set_tx_dev_volume(int device_id, int level);
|
||||
int q6audio_get_tx_dev_volume(int device_id);
|
||||
|
@ -132,6 +132,8 @@ uint32_t msm_rpc_get_vers(struct msm_rpc_endpoint *ept);
|
||||
/* check if server version can handle client requested version */
|
||||
int msm_rpc_is_compatible_version(uint32_t server_version,
|
||||
uint32_t client_version);
|
||||
struct msm_rpc_endpoint *msm_rpc_connect_compatible(uint32_t prog,
|
||||
uint32_t vers, unsigned flags);
|
||||
|
||||
int msm_rpc_close(struct msm_rpc_endpoint *ept);
|
||||
int msm_rpc_write(struct msm_rpc_endpoint *ept,
|
||||
@ -164,7 +166,7 @@ struct msm_rpc_xdr {
|
||||
void *in_buf;
|
||||
uint32_t in_size;
|
||||
uint32_t in_index;
|
||||
struct mutex in_lock;
|
||||
wait_queue_head_t in_buf_wait_q;
|
||||
|
||||
void *out_buf;
|
||||
uint32_t out_size;
|
||||
@ -174,6 +176,22 @@ struct msm_rpc_xdr {
|
||||
struct msm_rpc_endpoint *ept;
|
||||
};
|
||||
|
||||
int xdr_send_int8(struct msm_rpc_xdr *xdr, const int8_t *value);
|
||||
int xdr_send_uint8(struct msm_rpc_xdr *xdr, const uint8_t *value);
|
||||
int xdr_send_int16(struct msm_rpc_xdr *xdr, const int16_t *value);
|
||||
int xdr_send_uint16(struct msm_rpc_xdr *xdr, const uint16_t *value);
|
||||
int xdr_send_int32(struct msm_rpc_xdr *xdr, const int32_t *value);
|
||||
int xdr_send_uint32(struct msm_rpc_xdr *xdr, const uint32_t *value);
|
||||
int xdr_send_bytes(struct msm_rpc_xdr *xdr, const void **data, uint32_t *size);
|
||||
|
||||
int xdr_recv_int8(struct msm_rpc_xdr *xdr, int8_t *value);
|
||||
int xdr_recv_uint8(struct msm_rpc_xdr *xdr, uint8_t *value);
|
||||
int xdr_recv_int16(struct msm_rpc_xdr *xdr, int16_t *value);
|
||||
int xdr_recv_uint16(struct msm_rpc_xdr *xdr, uint16_t *value);
|
||||
int xdr_recv_int32(struct msm_rpc_xdr *xdr, int32_t *value);
|
||||
int xdr_recv_uint32(struct msm_rpc_xdr *xdr, uint32_t *value);
|
||||
int xdr_recv_bytes(struct msm_rpc_xdr *xdr, void **data, uint32_t *size);
|
||||
|
||||
struct msm_rpc_server
|
||||
{
|
||||
struct list_head list;
|
||||
|
@ -63,6 +63,8 @@ int smd_wait_until_writable(smd_channel_t *ch, int bytes);
|
||||
#endif
|
||||
int smd_wait_until_opened(smd_channel_t *ch, int timeout_us);
|
||||
|
||||
int smd_total_fifo_size(smd_channel_t *ch);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SMD_PORT_DS = 0,
|
||||
|
@ -142,13 +142,15 @@ int msm_irq_idle_sleep_allowed(void);
|
||||
int msm_irq_pending(void);
|
||||
int clks_allow_tcxo_locked_debug(void);
|
||||
extern int board_mfg_mode(void);
|
||||
extern char * board_get_mfg_sleep_gpio_table(void);
|
||||
extern unsigned long * board_get_mfg_sleep_gpio_table(void);
|
||||
extern void gpio_set_diag_gpio_table(unsigned long * dwMFG_gpio_table);
|
||||
extern void wait_rmt_final_call_back(int timeout);
|
||||
|
||||
#ifdef CONFIG_AXI_SCREEN_POLICY
|
||||
static int axi_rate;
|
||||
static int sleep_axi_rate;
|
||||
static struct clk *axi_clk;
|
||||
#endif
|
||||
static uint32_t *msm_pm_reset_vector;
|
||||
|
||||
static uint32_t msm_pm_max_sleep_time;
|
||||
@ -654,8 +656,8 @@ static int msm_wakeup_after; /* default, no wakeup by alarm */
|
||||
static int msm_power_wakeup_after(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
int ret;
|
||||
struct uart_port *port;
|
||||
struct msm_port *msm_port;
|
||||
//struct uart_port *port;
|
||||
//struct msm_port *msm_port;
|
||||
|
||||
ret = param_set_int(val, kp);
|
||||
printk(KERN_INFO "+msm_power_wakeup_after, ret=%d\r\n", ret);
|
||||
@ -681,7 +683,7 @@ static void msm_pm_power_off(void)
|
||||
|
||||
pmic_glb_power_down();
|
||||
|
||||
#if CONFIG_MSM_RMT_STORAGE_SERVER
|
||||
#ifdef CONFIG_MSM_RMT_STORAGE_SERVER
|
||||
printk(KERN_INFO "from %s\r\n", __func__);
|
||||
wait_rmt_final_call_back(10);
|
||||
printk(KERN_INFO "back %s\r\n", __func__);
|
||||
@ -715,7 +717,7 @@ void msm_pm_flush_console(void)
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MACH_HTCLEO)
|
||||
static void htcleo_save_reset_reason()
|
||||
static void htcleo_save_reset_reason(void)
|
||||
{
|
||||
/* save restart_reason to be accesible in bootloader @ ramconsole - 0x1000*/
|
||||
uint32_t *bootloader_reset_reason = ioremap(0x2FFB0000, PAGE_SIZE);
|
||||
@ -728,7 +730,7 @@ static void htcleo_save_reset_reason()
|
||||
}
|
||||
#endif
|
||||
|
||||
static void msm_pm_restart(char str)
|
||||
static void msm_pm_restart(char str, const char *cmd)
|
||||
{
|
||||
msm_pm_flush_console();
|
||||
|
||||
@ -742,7 +744,7 @@ static void msm_pm_restart(char str)
|
||||
else
|
||||
msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);
|
||||
|
||||
#if CONFIG_MSM_RMT_STORAGE_SERVER
|
||||
#ifdef CONFIG_MSM_RMT_STORAGE_SERVER
|
||||
printk(KERN_INFO "from %s\r\n", __func__);
|
||||
wait_rmt_final_call_back(10);
|
||||
printk(KERN_INFO "back %s\r\n", __func__);
|
||||
@ -858,6 +860,7 @@ void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns)
|
||||
EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
|
||||
|
||||
#ifdef CONFIG_EARLYSUSPEND
|
||||
#ifdef CONFIG_AXI_SCREEN_POLICY
|
||||
/* axi 128 screen on, 61mhz screen off */
|
||||
static void axi_early_suspend(struct early_suspend *handler)
|
||||
{
|
||||
@ -877,7 +880,9 @@ static struct early_suspend axi_screen_suspend = {
|
||||
.resume = axi_late_resume,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AXI_SCREEN_POLICY
|
||||
static void __init msm_pm_axi_init(void)
|
||||
{
|
||||
#ifdef CONFIG_EARLYSUSPEND
|
||||
@ -895,19 +900,18 @@ static void __init msm_pm_axi_init(void)
|
||||
axi_rate = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init msm_pm_init(void)
|
||||
{
|
||||
pm_power_off = msm_pm_power_off;
|
||||
arm_pm_restart = msm_pm_restart;
|
||||
msm_pm_max_sleep_time = 0;
|
||||
#if defined(CONFIG_ARCH_MSM_SCORPION)
|
||||
#ifdef CONFIG_AXI_SCREEN_POLICY
|
||||
msm_pm_axi_init();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
register_reboot_notifier(&msm_reboot_notifier);
|
||||
|
||||
msm_pm_reset_vector = ioremap(0x0, PAGE_SIZE);
|
||||
|
||||
#if defined(CONFIG_MACH_HTCLEO)
|
||||
|
@ -14,6 +14,7 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include "devices.h"
|
||||
#include "proc_comm.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* arch/arm/mach-msm/qdsp6/aac_in.c
|
||||
*
|
||||
/*
|
||||
* Copyright (C) 2009 Google, Inc.
|
||||
* Copyright (C) 2009 HTC Corporation
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@ -12,8 +12,9 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
@ -21,197 +22,449 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/msm_audio.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/msm_audio_1550.h>
|
||||
#include <linux/msm_audio_aac.h>
|
||||
#include <mach/msm_qdsp6_audio_1550.h>
|
||||
#include <mach/debug_mm.h>
|
||||
|
||||
#define BUFSZ (4096)
|
||||
#define DMASZ (BUFSZ * 2)
|
||||
#define AAC_FC_BUFF_CNT 10
|
||||
#define AAC_READ_TIMEOUT 2000
|
||||
struct aac_fc_buff {
|
||||
struct mutex lock;
|
||||
int empty;
|
||||
void *data;
|
||||
int size;
|
||||
int actual_size;
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define TRACE(x...) pr_info("Q6: "x)
|
||||
#else
|
||||
#define TRACE(x...) do{}while(0)
|
||||
#endif
|
||||
struct aac_fc {
|
||||
struct task_struct *task;
|
||||
wait_queue_head_t fc_wq;
|
||||
struct aac_fc_buff fc_buff[AAC_FC_BUFF_CNT];
|
||||
int buff_index;
|
||||
};
|
||||
struct aac {
|
||||
struct mutex lock;
|
||||
struct msm_audio_aac_enc_config cfg;
|
||||
struct msm_audio_stream_config str_cfg;
|
||||
struct audio_client *audio_client;
|
||||
struct msm_voicerec_mode voicerec_mode;
|
||||
struct aac_fc *aac_fc;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(aac_in_lock);
|
||||
static int aac_in_opened = 0;
|
||||
static struct aac_format *af;
|
||||
|
||||
void audio_client_dump(struct audio_client *ac);
|
||||
|
||||
static long aac_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case AUDIO_SET_VOLUME:
|
||||
break;
|
||||
case AUDIO_GET_STATS: {
|
||||
struct msm_audio_stats stats;
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
if (copy_to_user((void*) arg, &stats, sizeof(stats)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case AUDIO_START: {
|
||||
uint32_t acdb_id;
|
||||
rc = 0;
|
||||
|
||||
if (arg == 0) {
|
||||
acdb_id = 0;
|
||||
} else if (copy_from_user(&acdb_id,
|
||||
(void*) arg, sizeof(acdb_id))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_lock(&aac_in_lock);
|
||||
if (file->private_data) {
|
||||
rc = -EBUSY;
|
||||
} else {
|
||||
file->private_data = q6audio_open_aac(
|
||||
BUFSZ, 48000, AUDIO_FLAG_READ, af, acdb_id);
|
||||
if (!file->private_data)
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
mutex_unlock(&aac_in_lock);
|
||||
break;
|
||||
}
|
||||
case AUDIO_STOP:
|
||||
break;
|
||||
case AUDIO_FLUSH:
|
||||
break;
|
||||
case AUDIO_SET_CONFIG: {
|
||||
struct msm_audio_config config;
|
||||
if (copy_from_user(&config, (void*) arg, sizeof(config))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (config.sample_rate != 48000)
|
||||
pr_info("only 48KHz AAC encode supported\n");
|
||||
af->channel_config = config.channel_count;
|
||||
break;
|
||||
}
|
||||
case AUDIO_GET_CONFIG: {
|
||||
struct msm_audio_config config;
|
||||
config.buffer_size = BUFSZ;
|
||||
config.buffer_count = 2;
|
||||
config.sample_rate = 48000;
|
||||
config.channel_count = af->channel_config;
|
||||
config.unused[0] = 0;
|
||||
config.unused[1] = 0;
|
||||
config.unused[2] = 0;
|
||||
if (copy_to_user((void*) arg, &config, sizeof(config))) {
|
||||
rc = -EFAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int aac_in_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pr_info("aac_in: open\n");
|
||||
mutex_lock(&aac_in_lock);
|
||||
if (aac_in_opened) {
|
||||
pr_err("aac_in: busy\n");
|
||||
rc = -EBUSY;
|
||||
} else {
|
||||
af = kzalloc(sizeof(*af), GFP_KERNEL);
|
||||
memset(af, 0, sizeof(struct aac_format));
|
||||
af->sample_rate = 3; /* 48000 */
|
||||
af->channel_config = 1;
|
||||
af->block_formats = AUDIO_AAC_FORMAT_ADTS;
|
||||
af->audio_object_type = 2; /* CAD to ADSP format */
|
||||
af->bit_rate = 192000;
|
||||
|
||||
aac_in_opened = 1;
|
||||
rc = 0;
|
||||
}
|
||||
mutex_unlock(&aac_in_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t aac_in_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
static int q6_aac_flowcontrol(void *data)
|
||||
{
|
||||
struct audio_client *ac;
|
||||
struct audio_buffer *ab;
|
||||
const char __user *start = buf;
|
||||
int xfer, res = 0;
|
||||
struct aac *aac = data;
|
||||
int buff_index = 0;
|
||||
int xfer = 0;
|
||||
struct aac_fc *fc;
|
||||
|
||||
|
||||
ac = aac->audio_client;
|
||||
fc = aac->aac_fc;
|
||||
if (!ac) {
|
||||
pr_err("[%s:%s] audio_client is NULL\n", __MM_FILE__, __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
ab = ac->buf + ac->cpu_buf;
|
||||
if (ab->used)
|
||||
wait_event(ac->wait, (ab->used == 0));
|
||||
pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d\n", __MM_FILE__,
|
||||
__func__, ab->data, ac->cpu_buf);
|
||||
xfer = ab->actual_size;
|
||||
|
||||
mutex_lock(&(fc->fc_buff[buff_index].lock));
|
||||
if (!fc->fc_buff[buff_index].empty) {
|
||||
pr_err("[%s:%s] flow control buffer[%d] not read!\n",
|
||||
__MM_FILE__, __func__, buff_index);
|
||||
}
|
||||
|
||||
if (fc->fc_buff[buff_index].size < xfer) {
|
||||
pr_err("[%s:%s] buffer %d too small\n", __MM_FILE__,
|
||||
__func__, buff_index);
|
||||
memcpy(fc->fc_buff[buff_index].data,
|
||||
ab->data, fc->fc_buff[buff_index].size);
|
||||
fc->fc_buff[buff_index].empty = 0;
|
||||
fc->fc_buff[buff_index].actual_size =
|
||||
fc->fc_buff[buff_index].size;
|
||||
} else {
|
||||
memcpy(fc->fc_buff[buff_index].data, ab->data, xfer);
|
||||
fc->fc_buff[buff_index].empty = 0;
|
||||
fc->fc_buff[buff_index].actual_size = xfer;
|
||||
}
|
||||
mutex_unlock(&(fc->fc_buff[buff_index].lock));
|
||||
/*wake up client, if any*/
|
||||
wake_up(&fc->fc_wq);
|
||||
|
||||
buff_index++;
|
||||
if (buff_index >= AAC_FC_BUFF_CNT)
|
||||
buff_index = 0;
|
||||
|
||||
ab->used = 1;
|
||||
|
||||
q6audio_read(ac, ab);
|
||||
ac->cpu_buf ^= 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static long q6_aac_in_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct aac *aac = file->private_data;
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
struct aac_fc *fc;
|
||||
int size = 0;
|
||||
|
||||
mutex_lock(&aac->lock);
|
||||
switch (cmd) {
|
||||
case AUDIO_SET_VOLUME:
|
||||
break;
|
||||
case AUDIO_GET_STATS:
|
||||
{
|
||||
struct msm_audio_stats stats;
|
||||
pr_debug("[%s:%s] GET_STATS\n", __MM_FILE__, __func__);
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case AUDIO_START:
|
||||
{
|
||||
uint32_t acdb_id;
|
||||
pr_debug("[%s:%s] AUDIO_START\n", __MM_FILE__, __func__);
|
||||
if (arg == 0) {
|
||||
acdb_id = 0;
|
||||
} else {
|
||||
if (copy_from_user(&acdb_id, (void *) arg,
|
||||
sizeof(acdb_id))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aac->audio_client) {
|
||||
rc = -EBUSY;
|
||||
pr_err("[%s:%s] active session already existing\n",
|
||||
__MM_FILE__, __func__);
|
||||
break;
|
||||
} else {
|
||||
aac->audio_client = q6audio_open_aac(
|
||||
aac->str_cfg.buffer_size,
|
||||
aac->cfg.sample_rate,
|
||||
aac->cfg.channels,
|
||||
aac->cfg.bit_rate,
|
||||
aac->cfg.stream_format,
|
||||
aac->voicerec_mode.rec_mode, acdb_id);
|
||||
|
||||
if (aac->audio_client < 0) {
|
||||
pr_err("[%s:%s] aac open session failed\n",
|
||||
__MM_FILE__, __func__);
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*allocate flow control buffers*/
|
||||
fc = aac->aac_fc;
|
||||
size = ((aac->str_cfg.buffer_size < 1543) ? 1543 :
|
||||
aac->str_cfg.buffer_size);
|
||||
for (i = 0; i < AAC_FC_BUFF_CNT; ++i) {
|
||||
mutex_init(&(fc->fc_buff[i].lock));
|
||||
fc->fc_buff[i].empty = 1;
|
||||
fc->fc_buff[i].data = kmalloc(size, GFP_KERNEL);
|
||||
if (fc->fc_buff[i].data == NULL) {
|
||||
pr_err("[%s:%s] No memory for FC buffers\n",
|
||||
__MM_FILE__, __func__);
|
||||
rc = -ENOMEM;
|
||||
goto fc_fail;
|
||||
}
|
||||
fc->fc_buff[i].size = size;
|
||||
fc->fc_buff[i].actual_size = 0;
|
||||
}
|
||||
|
||||
/*create flow control thread*/
|
||||
fc->task = kthread_run(q6_aac_flowcontrol,
|
||||
aac, "aac_flowcontrol");
|
||||
if (IS_ERR(fc->task)) {
|
||||
rc = PTR_ERR(fc->task);
|
||||
pr_err("[%s:%s] error creating flow control thread\n",
|
||||
__MM_FILE__, __func__);
|
||||
goto fc_fail;
|
||||
}
|
||||
break;
|
||||
fc_fail:
|
||||
/*free flow control buffers*/
|
||||
--i;
|
||||
for (; i >= 0; i--) {
|
||||
kfree(fc->fc_buff[i].data);
|
||||
fc->fc_buff[i].data = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUDIO_STOP:
|
||||
pr_debug("[%s:%s] AUDIO_STOP\n", __MM_FILE__, __func__);
|
||||
break;
|
||||
case AUDIO_FLUSH:
|
||||
break;
|
||||
case AUDIO_SET_INCALL: {
|
||||
pr_debug("[%s:%s] SET_INCALL\n", __MM_FILE__, __func__);
|
||||
if (copy_from_user(&aac->voicerec_mode,
|
||||
(void *)arg, sizeof(struct msm_voicerec_mode)))
|
||||
rc = -EFAULT;
|
||||
|
||||
if (aac->voicerec_mode.rec_mode != AUDIO_FLAG_READ
|
||||
&& aac->voicerec_mode.rec_mode !=
|
||||
AUDIO_FLAG_INCALL_MIXED) {
|
||||
aac->voicerec_mode.rec_mode = AUDIO_FLAG_READ;
|
||||
pr_err("[%s:%s] Invalid rec_mode\n", __MM_FILE__,
|
||||
__func__);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUDIO_GET_STREAM_CONFIG:
|
||||
if (copy_to_user((void *)arg, &aac->str_cfg,
|
||||
sizeof(struct msm_audio_stream_config)))
|
||||
rc = -EFAULT;
|
||||
pr_debug("[%s:%s] GET_STREAM_CONFIG: buffsz=%d, buffcnt=%d\n",
|
||||
__MM_FILE__, __func__, aac->str_cfg.buffer_size,
|
||||
aac->str_cfg.buffer_count);
|
||||
break;
|
||||
case AUDIO_SET_STREAM_CONFIG:
|
||||
if (copy_from_user(&aac->str_cfg, (void *)arg,
|
||||
sizeof(struct msm_audio_stream_config))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
pr_debug("[%s:%s] SET_STREAM_CONFIG: buffsz=%d, buffcnt=%d\n",
|
||||
__MM_FILE__, __func__, aac->str_cfg.buffer_size,
|
||||
aac->str_cfg.buffer_count);
|
||||
if (aac->str_cfg.buffer_size < 1543) {
|
||||
pr_err("[%s:%s] Buffer size too small\n", __MM_FILE__,
|
||||
__func__);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (aac->str_cfg.buffer_count != 2)
|
||||
pr_info("[%s:%s] Buffer count set to 2\n", __MM_FILE__,
|
||||
__func__);
|
||||
|
||||
break;
|
||||
case AUDIO_SET_AAC_ENC_CONFIG:
|
||||
if (copy_from_user(&aac->cfg, (void *) arg,
|
||||
sizeof(struct msm_audio_aac_enc_config))) {
|
||||
rc = -EFAULT;
|
||||
}
|
||||
pr_debug("[%s:%s] SET_AAC_ENC_CONFIG: channels=%d, rate=%d\n",
|
||||
__MM_FILE__, __func__, aac->cfg.channels,
|
||||
aac->cfg.sample_rate);
|
||||
if (aac->cfg.channels < 1 || aac->cfg.channels > 2) {
|
||||
pr_err("[%s:%s]invalid number of channels\n",
|
||||
__MM_FILE__, __func__);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
if (aac->cfg.sample_rate != 48000) {
|
||||
pr_err("[%s:%s] only 48KHz is supported\n",
|
||||
__MM_FILE__, __func__);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
if (aac->cfg.stream_format != AUDIO_AAC_FORMAT_RAW &&
|
||||
aac->cfg.stream_format != AUDIO_AAC_FORMAT_ADTS) {
|
||||
pr_err("[%s:%s] unsupported AAC format\n", __MM_FILE__,
|
||||
__func__);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case AUDIO_GET_AAC_ENC_CONFIG:
|
||||
if (copy_to_user((void *) arg, &aac->cfg,
|
||||
sizeof(struct msm_audio_aac_enc_config))) {
|
||||
rc = -EFAULT;
|
||||
}
|
||||
pr_debug("[%s:%s] GET_AAC_ENC_CONFIG: channels=%d, rate=%d\n",
|
||||
__MM_FILE__, __func__, aac->cfg.channels,
|
||||
aac->cfg.sample_rate);
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&aac->lock);
|
||||
pr_debug("[%s:%s] rc = %d\n", __MM_FILE__, __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int q6_aac_in_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
|
||||
struct aac *aac;
|
||||
struct aac_fc *fc;
|
||||
int i;
|
||||
pr_info("[%s:%s] open\n", __MM_FILE__, __func__);
|
||||
aac = kmalloc(sizeof(struct aac), GFP_KERNEL);
|
||||
if (aac == NULL) {
|
||||
pr_err("[%s:%s] Could not allocate memory for aac driver\n",
|
||||
__MM_FILE__, __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_init(&aac->lock);
|
||||
file->private_data = aac;
|
||||
aac->audio_client = NULL;
|
||||
aac->str_cfg.buffer_size = 1543;
|
||||
aac->str_cfg.buffer_count = 2;
|
||||
aac->cfg.channels = 1;
|
||||
aac->cfg.bit_rate = 192000;
|
||||
aac->cfg.stream_format = AUDIO_AAC_FORMAT_ADTS;
|
||||
aac->cfg.sample_rate = 48000;
|
||||
aac->voicerec_mode.rec_mode = AUDIO_FLAG_READ;
|
||||
|
||||
aac->aac_fc = kmalloc(sizeof(struct aac_fc), GFP_KERNEL);
|
||||
if (aac->aac_fc == NULL) {
|
||||
pr_err("[%s:%s] Could not allocate memory for aac_fc\n",
|
||||
__MM_FILE__, __func__);
|
||||
kfree(aac);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fc = aac->aac_fc;
|
||||
fc->task = NULL;
|
||||
fc->buff_index = 0;
|
||||
for (i = 0; i < AAC_FC_BUFF_CNT; ++i) {
|
||||
fc->fc_buff[i].data = NULL;
|
||||
fc->fc_buff[i].size = 0;
|
||||
fc->fc_buff[i].actual_size = 0;
|
||||
}
|
||||
/*initialize wait queue head*/
|
||||
init_waitqueue_head(&fc->fc_wq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t q6_aac_in_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
struct audio_client *ac;
|
||||
const char __user *start = buf;
|
||||
struct aac *aac = file->private_data;
|
||||
struct aac_fc *fc;
|
||||
int xfer = 0;
|
||||
int res = 0;
|
||||
|
||||
pr_debug("[%s:%s] count = %d\n", __MM_FILE__, __func__, count);
|
||||
mutex_lock(&aac->lock);
|
||||
ac = aac->audio_client;
|
||||
|
||||
mutex_lock(&aac_in_lock);
|
||||
ac = file->private_data;
|
||||
if (!ac) {
|
||||
res = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
while (count > 0) {
|
||||
ab = ac->buf + ac->cpu_buf;
|
||||
fc = aac->aac_fc;
|
||||
|
||||
if (ab->used)
|
||||
if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
|
||||
audio_client_dump(ac);
|
||||
pr_err("aac_read: timeout. dsp dead?\n");
|
||||
BUG();
|
||||
}
|
||||
/*wait for buffer to full*/
|
||||
if (fc->fc_buff[fc->buff_index].empty != 0) {
|
||||
res = wait_event_interruptible_timeout(fc->fc_wq,
|
||||
(fc->fc_buff[fc->buff_index].empty == 0),
|
||||
msecs_to_jiffies(AAC_READ_TIMEOUT));
|
||||
|
||||
xfer = count;
|
||||
if (xfer > ab->size)
|
||||
xfer = ab->size;
|
||||
|
||||
if (copy_to_user(buf, ab->data, xfer)) {
|
||||
res = -EFAULT;
|
||||
pr_debug("[%s:%s] buff_index = %d\n", __MM_FILE__,
|
||||
__func__, fc->buff_index);
|
||||
if (res == 0) {
|
||||
pr_err("[%s:%s] Timeout!\n", __MM_FILE__, __func__);
|
||||
res = -ETIMEDOUT;
|
||||
goto fail;
|
||||
} else if (res < 0) {
|
||||
pr_err("[%s:%s] Returning on Interrupt\n", __MM_FILE__,
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buf += xfer;
|
||||
count -= xfer;
|
||||
|
||||
ab->used = 1;
|
||||
q6audio_read(ac, ab);
|
||||
ac->cpu_buf ^= 1;
|
||||
}
|
||||
fail:
|
||||
/*lock the buffer*/
|
||||
mutex_lock(&(fc->fc_buff[fc->buff_index].lock));
|
||||
xfer = fc->fc_buff[fc->buff_index].actual_size;
|
||||
|
||||
if (xfer > count) {
|
||||
mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
|
||||
pr_err("[%s:%s] read failed! byte count too small\n",
|
||||
__MM_FILE__, __func__);
|
||||
res = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (copy_to_user(buf, fc->fc_buff[fc->buff_index].data, xfer)) {
|
||||
mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
|
||||
pr_err("[%s:%s] copy_to_user failed at index %d\n",
|
||||
__MM_FILE__, __func__, fc->buff_index);
|
||||
res = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buf += xfer;
|
||||
|
||||
fc->fc_buff[fc->buff_index].empty = 1;
|
||||
fc->fc_buff[fc->buff_index].actual_size = 0;
|
||||
|
||||
mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
|
||||
++(fc->buff_index);
|
||||
if (fc->buff_index >= AAC_FC_BUFF_CNT)
|
||||
fc->buff_index = 0;
|
||||
|
||||
res = buf - start;
|
||||
mutex_unlock(&aac_in_lock);
|
||||
fail:
|
||||
mutex_unlock(&aac->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int aac_in_release(struct inode *inode, struct file *file)
|
||||
static int q6_aac_in_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int rc = 0;
|
||||
pr_info("aac_in: release\n");
|
||||
mutex_lock(&aac_in_lock);
|
||||
if (file->private_data)
|
||||
rc = q6audio_close(file->private_data);
|
||||
kfree(af);
|
||||
aac_in_opened = 0;
|
||||
mutex_unlock(&aac_in_lock);
|
||||
struct aac *aac = file->private_data;
|
||||
int i = 0;
|
||||
struct aac_fc *fc;
|
||||
|
||||
mutex_lock(&aac->lock);
|
||||
fc = aac->aac_fc;
|
||||
kthread_stop(fc->task);
|
||||
fc->task = NULL;
|
||||
|
||||
/*free flow control buffers*/
|
||||
for (i = 0; i < AAC_FC_BUFF_CNT; ++i) {
|
||||
kfree(fc->fc_buff[i].data);
|
||||
fc->fc_buff[i].data = NULL;
|
||||
}
|
||||
kfree(fc);
|
||||
if (aac->audio_client)
|
||||
rc = q6audio_close(aac->audio_client);
|
||||
mutex_unlock(&aac->lock);
|
||||
kfree(aac);
|
||||
pr_info("[%s:%s] release\n", __MM_FILE__, __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct file_operations aac_in_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = aac_in_open,
|
||||
.read = aac_in_read,
|
||||
.release = aac_in_release,
|
||||
.unlocked_ioctl = aac_in_ioctl,
|
||||
static const struct file_operations q6_aac_in_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = q6_aac_in_open,
|
||||
.read = q6_aac_in_read,
|
||||
.release = q6_aac_in_release,
|
||||
.unlocked_ioctl = q6_aac_in_ioctl,
|
||||
};
|
||||
|
||||
struct miscdevice aac_in_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "msm_aac_in",
|
||||
.fops = &aac_in_fops,
|
||||
struct miscdevice q6_aac_in_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "msm_aac_in",
|
||||
.fops = &q6_aac_in_fops,
|
||||
};
|
||||
|
||||
static int __init aac_in_init(void) {
|
||||
return misc_register(&aac_in_misc);
|
||||
static int __init q6_aac_in_init(void)
|
||||
{
|
||||
return misc_register(&q6_aac_in_misc);
|
||||
}
|
||||
|
||||
device_initcall(aac_in_init);
|
||||
device_initcall(q6_aac_in_init);
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/msm_audio.h>
|
||||
#include <linux/msm_audio_1550.h>
|
||||
|
||||
#include <mach/msm_qdsp6_audio_1550.h>
|
||||
#include <mach/htc_acoustic_qsd.h>
|
||||
@ -133,8 +133,7 @@ static int q6_open(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int q6_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long q6_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int rc;
|
||||
uint32_t n;
|
||||
@ -147,28 +146,40 @@ static int q6_ioctl(struct inode *inode, struct file *file,
|
||||
case AUDIO_SWITCH_DEVICE:
|
||||
rc = copy_from_user(&id, (void *)arg, sizeof(id));
|
||||
AUDIO_INFO("SWITCH DEVICE %d, acdb %d\n", id[0], id[1]);
|
||||
if (!rc)
|
||||
if (rc) {
|
||||
pr_err("%s: bad user address\n", __func__);
|
||||
rc = -EFAULT;
|
||||
} else
|
||||
rc = q6audio_do_routing(id[0], id[1]);
|
||||
break;
|
||||
case AUDIO_SET_VOLUME:
|
||||
rc = copy_from_user(&n, (void *)arg, sizeof(n));
|
||||
if (!rc)
|
||||
if (rc) {
|
||||
pr_err("%s: bad user address\n", __func__);
|
||||
rc = -EFAULT;
|
||||
} else
|
||||
rc = q6audio_set_rx_volume(n);
|
||||
break;
|
||||
case AUDIO_SET_MUTE:
|
||||
rc = copy_from_user(&n, (void *)arg, sizeof(n));
|
||||
if (!rc)
|
||||
if (rc) {
|
||||
pr_err("%s: bad user address\n", __func__);
|
||||
rc = -EFAULT;
|
||||
} else
|
||||
rc = q6audio_set_tx_mute(n);
|
||||
break;
|
||||
case AUDIO_UPDATE_ACDB:
|
||||
rc = copy_from_user(&id, (void *)arg, sizeof(id));
|
||||
if (!rc)
|
||||
if (rc) {
|
||||
pr_err("%s: bad user address\n", __func__);
|
||||
rc = -EFAULT;
|
||||
} else
|
||||
rc = q6audio_update_acdb(id[0], id[1]);
|
||||
break;
|
||||
case AUDIO_START_VOICE:
|
||||
if (arg == 0) {
|
||||
if (arg == 0)
|
||||
id[0] = id[1] = 0;
|
||||
} else if (copy_from_user(&id, (void*) arg, sizeof(id))) {
|
||||
else if (copy_from_user(&id, (void*) arg, sizeof(id))) {
|
||||
pr_info("voice: copy acdb_id from user failed\n");
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/android_pmem.h>
|
||||
@ -358,7 +359,7 @@ static int q6_encode(struct q6venc_dev *q6venc, struct encode_param *enc_param)
|
||||
{
|
||||
struct q6_encode_param *q6_param = &enc_param->q6_encode_param;
|
||||
struct file *file;
|
||||
struct buf_info *buf;
|
||||
struct buf_info *buf = 0;
|
||||
int i;
|
||||
int ret;
|
||||
int rlc_buf_index;
|
||||
|
@ -14,6 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
@ -64,6 +65,12 @@ static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
switch (cmd) {
|
||||
case AUDIO_SET_VOLUME: {
|
||||
int vol;
|
||||
if (!pcm->ac) {
|
||||
pr_err("%s: cannot set volume before AUDIO_START!\n",
|
||||
__func__);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (copy_from_user(&vol, (void*) arg, sizeof(vol))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/clk.h>
|
||||
@ -32,11 +33,12 @@
|
||||
#include "dal_acdb.h"
|
||||
#include "dal_adie.h"
|
||||
#include <mach/msm_qdsp6_audio_1550.h>
|
||||
#include <linux/msm_audio.h>
|
||||
#include <linux/msm_audio_1550.h>
|
||||
#include <mach/htc_acoustic_qsd.h>
|
||||
#include <mach/msm_audio_qcp.h>
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/msm_audio_aac.h>
|
||||
|
||||
#include "q6audio_devices.h"
|
||||
#include "../dex_comm.h"
|
||||
@ -172,7 +174,7 @@ static struct audio_client * audio_test(void);
|
||||
static void callback(void *data, int len, void *cookie);
|
||||
static int audio_init(struct audio_client *ac);
|
||||
static int audio_info(struct audio_client *ac);
|
||||
static int q6audio_init_rx_volumes();
|
||||
static int q6audio_init_rx_volumes(void);
|
||||
|
||||
static struct wake_lock wakelock;
|
||||
static struct wake_lock idlelock;
|
||||
@ -215,6 +217,7 @@ static char acdb_file[64] = "default.acdb";
|
||||
static uint32_t tx_acdb = 0;
|
||||
static uint32_t rx_acdb = 0;
|
||||
static int acdb_use_rpc = 0;
|
||||
static int acdb_use_map = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// helper functions for device parameters
|
||||
@ -699,10 +702,18 @@ static int audio_mp3_open(struct audio_client *ac, uint32_t bufsz,
|
||||
return ac->open_status;
|
||||
}
|
||||
|
||||
static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
|
||||
/*
|
||||
* ported code for audio_aac_open from Code Aurora in order to work
|
||||
* with new aac code from Code Aurora
|
||||
* by marc1706
|
||||
*/
|
||||
static int audio_aac_open(struct audio_client *ac, uint32_t bufsz,
|
||||
uint32_t sample_rate, uint32_t channels,
|
||||
uint32_t bit_rate, uint32_t flags,
|
||||
uint32_t stream_format)
|
||||
{
|
||||
int r;
|
||||
struct aac_format *af = data;
|
||||
int audio_object_type;
|
||||
struct adsp_open_command rpc;
|
||||
uint32_t *aac_type;
|
||||
int idx = 0; // sizeof(uint32_t);
|
||||
@ -723,77 +734,33 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
|
||||
rpc.pblock = params_phys;
|
||||
|
||||
aac_type = (uint32_t *)(fmt->data);
|
||||
switch (af->block_formats)
|
||||
switch (stream_format)
|
||||
{
|
||||
case 0xffff:
|
||||
if (ac->flags & AUDIO_FLAG_WRITE)
|
||||
*aac_type = ADSP_AUDIO_AAC_ADTS;
|
||||
else
|
||||
*aac_type = ADSP_AUDIO_AAC_MPEG4_ADTS;
|
||||
break;
|
||||
case 0:
|
||||
if (ac->flags & AUDIO_FLAG_WRITE)
|
||||
*aac_type = ADSP_AUDIO_AAC_ADIF;
|
||||
else
|
||||
*aac_type = ADSP_AUDIO_AAC_RAW;
|
||||
break;
|
||||
case 1:
|
||||
*aac_type = ADSP_AUDIO_AAC_RAW;
|
||||
break;
|
||||
case 2:
|
||||
*aac_type = ADSP_AUDIO_AAC_LOAS;
|
||||
break;
|
||||
case 3:
|
||||
*aac_type = ADSP_AUDIO_AAC_FRAMED_RAW;
|
||||
break;
|
||||
case 4:
|
||||
*aac_type = ADSP_AUDIO_AAC_RAW;
|
||||
break;
|
||||
case AUDIO_AAC_FORMAT_ADTS:
|
||||
/* AAC Encoder expect MPEG4_ADTS media type */
|
||||
*aac_type = ADSP_AUDIO_AAC_MPEG4_ADTS;
|
||||
break;
|
||||
case AUDIO_AAC_FORMAT_RAW:
|
||||
/* for ADIF recording */
|
||||
*aac_type = ADSP_AUDIO_AAC_RAW;
|
||||
break;
|
||||
default:
|
||||
pr_err("unsupported AAC type %d\n", af->block_formats);
|
||||
pr_err("unsupported AAC type %d\n", stream_format);
|
||||
mutex_unlock(&open_mem_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* AAC OBJECT LC */
|
||||
audio_object_type = 2;
|
||||
|
||||
AUDIO_INFO("aac_open: type %x, obj %d, idx %d\n",
|
||||
*aac_type, af->audio_object_type, idx);
|
||||
fmt->data[idx++] = (u8)(((af->audio_object_type & 0x1F) << 3) |
|
||||
((af->sample_rate >> 1) & 0x7));
|
||||
fmt->data[idx] = (u8)(((af->sample_rate & 0x1) << 7) |
|
||||
((af->channel_config & 0x7) << 3));
|
||||
*aac_type, audio_object_type, idx);
|
||||
|
||||
switch (af->audio_object_type) {
|
||||
case AAC_OBJECT_ER_LC:
|
||||
case AAC_OBJECT_ER_LTP:
|
||||
case AAC_OBJECT_ER_LD:
|
||||
/* extension flag */
|
||||
fmt->data[idx++] |= 0x1;
|
||||
fmt->data[idx] = (u8)(
|
||||
((af->aac_section_data_resilience_flag & 0x1) << 7) |
|
||||
((af->aac_scalefactor_data_resilience_flag & 0x1) << 6) |
|
||||
((af->aac_spectral_data_resilience_flag & 0x1) << 5) |
|
||||
((af->ep_config & 0x3) << 2));
|
||||
break;
|
||||
fmt->data[idx++] = (u8)(((audio_object_type & 0x1F) << 3) |
|
||||
((sample_rate >> 1) & 0x7));
|
||||
fmt->data[idx] = (u8)(((sample_rate & 0x1) << 7) |
|
||||
((channels & 0x7) << 3));
|
||||
|
||||
case AAC_OBJECT_ER_SCALABLE:
|
||||
fmt->data[idx++] |= 0x1;
|
||||
/* extension flag */
|
||||
fmt->data[idx++] = (u8)(
|
||||
((af->aac_section_data_resilience_flag & 0x1) << 4) |
|
||||
((af->aac_scalefactor_data_resilience_flag & 0x1) << 3) |
|
||||
((af->aac_spectral_data_resilience_flag & 0x1) << 2) |
|
||||
((af->ep_config >> 1) & 0x1));
|
||||
fmt->data[idx] = (u8)((af->ep_config & 0x1) << 7);
|
||||
break;
|
||||
|
||||
case AAC_OBJECT_BSAC:
|
||||
fmt->data[++idx] = (u8)((af->ep_config & 0x3) << 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("dbg unknown object type \n");
|
||||
break;
|
||||
}
|
||||
// fmt->num_bytes = idx + 1;
|
||||
rpc.blocklen = idx + 1;
|
||||
|
||||
@ -801,8 +768,8 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
|
||||
fmt->data[0], fmt->data[1], fmt->data[2], fmt->data[3],
|
||||
fmt->data[4], fmt->data[5], fmt->data[6], fmt->data[7]);
|
||||
|
||||
rpc.config.aac.bit_rate = af->bit_rate;
|
||||
if (ac->flags & AUDIO_FLAG_WRITE)
|
||||
rpc.config.aac.bit_rate = bit_rate;
|
||||
if (flags & AUDIO_FLAG_WRITE)
|
||||
{
|
||||
rpc.opcode = ADSP_AUDIO_OPCODE_OPEN_WRITE;
|
||||
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_PLAYBACK;
|
||||
@ -813,25 +780,13 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
|
||||
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_RECORD;
|
||||
}
|
||||
|
||||
if ((af->sbr_on_flag == 0) && (af->sbr_ps_on_flag == 0))
|
||||
{
|
||||
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE;
|
||||
}
|
||||
else if ((af->sbr_on_flag == 1) && (af->sbr_ps_on_flag == 0))
|
||||
{
|
||||
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_AAC_PLUS_MODE;
|
||||
}
|
||||
else if ((af->sbr_on_flag == 1) && (af->sbr_ps_on_flag == 1))
|
||||
{
|
||||
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_ENHANCED_AAC_PLUS_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pr_err("unsupported SBR flag\n");
|
||||
mutex_unlock(&open_mem_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
rpc.buf_max_size = bufsz; /* XXX ??? */
|
||||
/*
|
||||
* Always use ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE as encoder_mode
|
||||
* from Code Aurora
|
||||
* by marc1706
|
||||
*/
|
||||
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE;
|
||||
rpc.buf_max_size = bufsz;
|
||||
|
||||
TRACE("aac_open: opcode %x, stream_context 0x%x, "
|
||||
"mode %d, bytes %d, bbuffer size %d\n",
|
||||
@ -1233,11 +1188,29 @@ static int acdb_init(char *filename)
|
||||
const struct firmware *fw;
|
||||
int n;
|
||||
|
||||
// return -ENODEV;
|
||||
AUDIO_INFO("%s\n", __func__);
|
||||
#ifdef CONFIG_MACH_HTCLEO
|
||||
pr_info("acdb: trying htcleo.acdb\n");
|
||||
if(request_firmware(&fw, "htcleo.acdb", q6_control_device.this_device) < 0) {
|
||||
pr_info("acdb: load 'htcleo.acdb' failed, trying 'default.acdb'\n");
|
||||
acdb_use_map = 0;
|
||||
if (request_firmware(&fw, filename, q6_control_device.this_device) < 0) {
|
||||
pr_err("acdb: load 'default.acdb' failed...\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
pr_info("acdb: 'htcleo.acdb' found, using translation\n");
|
||||
acdb_use_map = 1;
|
||||
}
|
||||
#else
|
||||
pr_info("acdb: load '%s'\n", filename);
|
||||
acd_use_map = 0;
|
||||
if (request_firmware(&fw, filename, q6_control_device.this_device) < 0) {
|
||||
pr_err("acdb: load 'default.acdb' failed...\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
db = (void*) fw->data;
|
||||
|
||||
if (fw->size < sizeof(struct audio_config_database)) {
|
||||
@ -1448,6 +1421,9 @@ static int acdb_get_config_table(uint32_t device_id, uint32_t sample_rate)
|
||||
int n;
|
||||
|
||||
printk("table\n");
|
||||
// htcleo use custom table with wince values, it must be mapped
|
||||
if(acdb_use_map)
|
||||
device_id = map_cad_dev_to_virtual(device_id);
|
||||
db = acdb_data;
|
||||
for (n = 0; n < db->entry_count; n++)
|
||||
{
|
||||
@ -2209,7 +2185,7 @@ int q6audio_set_rx_volume(int level)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6audio_set_rx_volume);
|
||||
|
||||
static int q6audio_init_rx_volumes()
|
||||
static int q6audio_init_rx_volumes(void)
|
||||
{
|
||||
int vol;
|
||||
struct q6_device_info *di = q6_audio_devices;
|
||||
@ -2628,14 +2604,19 @@ int q6audio_async(struct audio_client *ac)
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
|
||||
uint32_t flags, void *data, uint32_t acdb_id)
|
||||
/*
|
||||
* ported code for q6audio_open_aac from Code Aurora
|
||||
* by marc1706
|
||||
*/
|
||||
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t samplerate,
|
||||
uint32_t channels, uint32_t bitrate,
|
||||
uint32_t stream_format, uint32_t flags,
|
||||
uint32_t acdb_id)
|
||||
{
|
||||
struct audio_client *ac;
|
||||
|
||||
AUDIO_INFO("%s\n", __func__);
|
||||
TRACE("q6audio_open_aac flags=%d rate=%d\n", flags, rate);
|
||||
TRACE("q6audio_open_aac flags=%d samplerate=%d, channels = %d\n", flags, samplerate, channels);
|
||||
|
||||
if (q6audio_init())
|
||||
return 0;
|
||||
@ -2648,12 +2629,13 @@ struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
|
||||
if (ac->flags & AUDIO_FLAG_WRITE)
|
||||
audio_rx_path_enable(1, acdb_id);
|
||||
else {
|
||||
/* TODO: consider concourrency with voice call */
|
||||
tx_clk_freq = rate;
|
||||
if (!audio_tx_path_refcount)
|
||||
tx_clk_freq = 48000;
|
||||
audio_tx_path_enable(1, acdb_id);
|
||||
}
|
||||
|
||||
audio_aac_open(ac, bufsz, data);
|
||||
audio_aac_open(ac, bufsz, samplerate, channels, bitrate, flags,
|
||||
stream_format);
|
||||
audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
|
||||
|
||||
if (!(ac->flags & AUDIO_FLAG_WRITE)) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/msm_audio.h>
|
||||
|
@ -188,6 +188,12 @@ static void sirc_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
(sirc_reg_table[reg].cascade_irq != irq))
|
||||
reg++;
|
||||
|
||||
if (reg == ARRAY_SIZE(sirc_reg_table)) {
|
||||
printk(KERN_ERR "%s: incorrect irq %d called\n",
|
||||
__func__, irq);
|
||||
return;
|
||||
}
|
||||
|
||||
status = readl(sirc_reg_table[reg].int_status);
|
||||
status &= SIRC_MASK;
|
||||
if (status == 0)
|
||||
|
@ -381,17 +381,18 @@ static void update_packet_state(struct smd_channel *ch)
|
||||
int r;
|
||||
|
||||
/* can't do anything if we're in the middle of a packet */
|
||||
if (ch->current_packet != 0)
|
||||
return;
|
||||
while (ch->current_packet == 0) {
|
||||
/* discard 0 length packets if any */
|
||||
|
||||
/* don't bother unless we can get the full header */
|
||||
if (smd_stream_read_avail(ch) < SMD_HEADER_SIZE)
|
||||
return;
|
||||
/* don't bother unless we can get the full header */
|
||||
if (smd_stream_read_avail(ch) < SMD_HEADER_SIZE)
|
||||
return;
|
||||
|
||||
r = ch_read(ch, hdr, SMD_HEADER_SIZE);
|
||||
BUG_ON(r != SMD_HEADER_SIZE);
|
||||
r = ch_read(ch, hdr, SMD_HEADER_SIZE);
|
||||
BUG_ON(r != SMD_HEADER_SIZE);
|
||||
|
||||
ch->current_packet = hdr[0];
|
||||
ch->current_packet = hdr[0];
|
||||
}
|
||||
}
|
||||
|
||||
/* provide a pointer and length to next free space in the fifo */
|
||||
@ -490,7 +491,7 @@ static void handle_smd_irq(struct list_head *list, void (*notify)(void))
|
||||
#ifdef CONFIG_BUILD_CIQ
|
||||
/* put here to make sure we got the disable/enable index */
|
||||
if (!msm_smd_ciq_info)
|
||||
msm_smd_ciq_info = (*(volatile uint32_t *)(MSM_SHARED_RAM_BASE + 0xFC11C));
|
||||
msm_smd_ciq_info = (*(volatile uint32_t *)(MSM_SHARED_RAM_BASE + SMD_CIQ_BASE));
|
||||
#endif
|
||||
spin_lock_irqsave(&smd_lock, flags);
|
||||
list_for_each_entry(ch, list, ch_list) {
|
||||
@ -641,6 +642,8 @@ static int smd_stream_write(smd_channel_t *ch, const void *_data, int len)
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
else if (len == 0)
|
||||
return 0;
|
||||
|
||||
while ((xfer = ch_write_buffer(ch, &ptr)) != 0) {
|
||||
if (!ch_is_open(ch))
|
||||
@ -911,6 +914,7 @@ int smd_close(smd_channel_t *ch)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(smd_close);
|
||||
|
||||
int smd_read(smd_channel_t *ch, void *data, int len)
|
||||
{
|
||||
@ -922,6 +926,7 @@ int smd_write(smd_channel_t *ch, const void *data, int len)
|
||||
{
|
||||
return ch->write(ch, data, len);
|
||||
}
|
||||
EXPORT_SYMBOL(smd_write);
|
||||
|
||||
int smd_write_atomic(smd_channel_t *ch, const void *data, int len)
|
||||
{
|
||||
@ -944,6 +949,7 @@ int smd_write_avail(smd_channel_t *ch)
|
||||
{
|
||||
return ch->write_avail(ch);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(smd_write_avail);
|
||||
|
||||
int smd_wait_until_readable(smd_channel_t *ch, int bytes)
|
||||
{
|
||||
@ -981,6 +987,11 @@ int smd_cur_packet_size(smd_channel_t *ch)
|
||||
}
|
||||
EXPORT_SYMBOL(smd_cur_packet_size);
|
||||
|
||||
/* Returns SMD buffer size */
|
||||
int smd_total_fifo_size(smd_channel_t *ch)
|
||||
{
|
||||
return ch->fifo_size;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -89,6 +89,33 @@ struct smsm_interrupt_info {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MSM_N_WAY_SMSM)
|
||||
enum {
|
||||
SMSM_APPS_STATE,
|
||||
SMSM_MODEM_STATE,
|
||||
SMSM_Q6_STATE,
|
||||
SMSM_APPS_DEM,
|
||||
SMSM_MODEM_DEM,
|
||||
SMSM_Q6_DEM,
|
||||
SMSM_POWER_MASTER_DEM,
|
||||
SMSM_TIME_MASTER_DEM,
|
||||
SMSM_NUM_ENTRIES,
|
||||
};
|
||||
#else
|
||||
enum {
|
||||
SMSM_APPS_STATE = 1,
|
||||
SMSM_MODEM_STATE = 3,
|
||||
SMSM_NUM_ENTRIES,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SMSM_APPS,
|
||||
SMSM_MODEM,
|
||||
SMSM_Q6,
|
||||
SMSM_NUM_HOSTS,
|
||||
};
|
||||
|
||||
#define SZ_DIAG_ERR_MSG 0xC8
|
||||
#define ID_DIAG_ERR_MSG SMEM_DIAG_ERR_MESSAGE
|
||||
#define ID_SMD_CHANNELS SMEM_SMD_BASE_ID
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/cdev.h>
|
||||
@ -105,7 +106,7 @@ static struct wake_lock rpcrouter_wake_lock;
|
||||
static int rpcrouter_need_len;
|
||||
|
||||
static atomic_t next_xid = ATOMIC_INIT(1);
|
||||
static uint8_t next_pacmarkid;
|
||||
static atomic_t next_mid = ATOMIC_INIT(0);
|
||||
|
||||
static void do_read_data(struct work_struct *work);
|
||||
static void do_create_pdevs(struct work_struct *work);
|
||||
@ -114,12 +115,16 @@ static void do_create_rpcrouter_pdev(struct work_struct *work);
|
||||
static DECLARE_WORK(work_read_data, do_read_data);
|
||||
static DECLARE_WORK(work_create_pdevs, do_create_pdevs);
|
||||
static DECLARE_WORK(work_create_rpcrouter_pdev, do_create_rpcrouter_pdev);
|
||||
static atomic_t rpcrouter_pdev_created = ATOMIC_INIT(0);
|
||||
|
||||
#define RR_STATE_IDLE 0
|
||||
#define RR_STATE_HEADER 1
|
||||
#define RR_STATE_BODY 2
|
||||
#define RR_STATE_ERROR 3
|
||||
|
||||
#define RMT_STORAGE_APIPROG_BE32 0xa7000030
|
||||
#define RMT_STORAGE_SRV_APIPROG_BE32 0x9c000030
|
||||
|
||||
struct rr_context {
|
||||
struct rr_packet *pkt;
|
||||
uint8_t *ptr;
|
||||
@ -262,6 +267,7 @@ struct msm_rpc_endpoint *msm_rpcrouter_create_local_endpoint(dev_t dev)
|
||||
{
|
||||
struct msm_rpc_endpoint *ept;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
ept = kmalloc(sizeof(struct msm_rpc_endpoint), GFP_KERNEL);
|
||||
if (!ept)
|
||||
@ -269,7 +275,9 @@ struct msm_rpc_endpoint *msm_rpcrouter_create_local_endpoint(dev_t dev)
|
||||
memset(ept, 0, sizeof(struct msm_rpc_endpoint));
|
||||
|
||||
/* mark no reply outstanding */
|
||||
ept->reply_pid = 0xffffffff;
|
||||
ept->next_rroute = 0;
|
||||
for (i = 0; i < MAX_REPLY_ROUTE; i++)
|
||||
ept->rroute[i].pid = 0xffffffff;
|
||||
|
||||
ept->cid = (uint32_t) ept;
|
||||
ept->pid = RPCROUTER_PID_LOCAL;
|
||||
@ -530,7 +538,8 @@ static int process_control_msg(union rr_control_msg *msg, int len)
|
||||
|
||||
static void do_create_rpcrouter_pdev(struct work_struct *work)
|
||||
{
|
||||
platform_device_register(&rpcrouter_pdev);
|
||||
if (atomic_cmpxchg(&rpcrouter_pdev_created, 0, 1) == 0)
|
||||
platform_device_register(&rpcrouter_pdev);
|
||||
}
|
||||
|
||||
static void do_create_pdevs(struct work_struct *work)
|
||||
@ -652,11 +661,13 @@ static void do_read_data(struct work_struct *work)
|
||||
|
||||
hdr.size -= sizeof(pm);
|
||||
|
||||
frag = rr_malloc(hdr.size + sizeof(*frag));
|
||||
frag = rr_malloc(sizeof(*frag));
|
||||
frag->next = NULL;
|
||||
frag->length = hdr.size;
|
||||
if (rr_read(frag->data, hdr.size))
|
||||
if (rr_read(frag->data, hdr.size)) {
|
||||
kfree(frag);
|
||||
goto fail_io;
|
||||
}
|
||||
|
||||
ept = rpcrouter_lookup_local_endpoint(hdr.dst_cid);
|
||||
if (!ept) {
|
||||
@ -758,19 +769,77 @@ int msm_rpc_close(struct msm_rpc_endpoint *ept)
|
||||
}
|
||||
EXPORT_SYMBOL(msm_rpc_close);
|
||||
|
||||
static int msm_rpc_write_pkt(struct msm_rpc_endpoint *ept,
|
||||
struct rr_remote_endpoint *r_ept,
|
||||
struct rr_header *hdr,
|
||||
uint32_t pacmark,
|
||||
void *buffer, int count)
|
||||
{
|
||||
DEFINE_WAIT(__wait);
|
||||
unsigned long flags;
|
||||
int needed;
|
||||
|
||||
for (;;) {
|
||||
prepare_to_wait(&r_ept->quota_wait, &__wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
spin_lock_irqsave(&r_ept->quota_lock, flags);
|
||||
if (r_ept->tx_quota_cntr < RPCROUTER_DEFAULT_RX_QUOTA)
|
||||
break;
|
||||
if (signal_pending(current) &&
|
||||
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE)))
|
||||
break;
|
||||
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
|
||||
schedule();
|
||||
}
|
||||
finish_wait(&r_ept->quota_wait, &__wait);
|
||||
|
||||
if (signal_pending(current) &&
|
||||
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE))) {
|
||||
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
r_ept->tx_quota_cntr++;
|
||||
if (r_ept->tx_quota_cntr == RPCROUTER_DEFAULT_RX_QUOTA)
|
||||
hdr->confirm_rx = 1;
|
||||
|
||||
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&smd_lock, flags);
|
||||
|
||||
needed = sizeof(*hdr) + hdr->size;
|
||||
while (smd_write_avail(smd_channel) < needed) {
|
||||
spin_unlock_irqrestore(&smd_lock, flags);
|
||||
msleep(250);
|
||||
spin_lock_irqsave(&smd_lock, flags);
|
||||
}
|
||||
|
||||
/* TODO: deal with full fifo */
|
||||
smd_write(smd_channel, hdr, sizeof(*hdr));
|
||||
smd_write(smd_channel, &pacmark, sizeof(pacmark));
|
||||
smd_write(smd_channel, buffer, count);
|
||||
|
||||
spin_unlock_irqrestore(&smd_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_rpc_write(struct msm_rpc_endpoint *ept, void *buffer, int count)
|
||||
{
|
||||
struct rr_header hdr;
|
||||
uint32_t pacmark;
|
||||
uint32_t mid;
|
||||
struct rpc_request_hdr *rq = buffer;
|
||||
struct rr_remote_endpoint *r_ept;
|
||||
unsigned long flags;
|
||||
int needed;
|
||||
DEFINE_WAIT(__wait);
|
||||
int ret;
|
||||
int total;
|
||||
|
||||
/* TODO: fragmentation for large outbound packets */
|
||||
if (count > (RPCROUTER_MSGSIZE_MAX - sizeof(uint32_t)) || !count)
|
||||
return -EINVAL;
|
||||
if (((rq->prog&0xFFFFFFF0) == RMT_STORAGE_APIPROG_BE32) ||
|
||||
((rq->prog&0xFFFFFFF0) == RMT_STORAGE_SRV_APIPROG_BE32)) {
|
||||
printk(KERN_DEBUG
|
||||
"rpc_write: prog = %x , procedure = %d, type = %d, xid = %d\n"
|
||||
, be32_to_cpu(rq->prog), be32_to_cpu(rq->procedure)
|
||||
, be32_to_cpu(rq->type), be32_to_cpu(rq->xid));
|
||||
}
|
||||
|
||||
/* snoop the RPC packet and enforce permissions */
|
||||
|
||||
@ -818,23 +887,21 @@ int msm_rpc_write(struct msm_rpc_endpoint *ept, void *buffer, int count)
|
||||
} else {
|
||||
/* RPC REPLY */
|
||||
/* TODO: locking */
|
||||
if (ept->reply_pid == 0xffffffff) {
|
||||
printk(KERN_ERR
|
||||
"rr_write: rejecting unexpected reply\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ept->reply_xid != rq->xid) {
|
||||
printk(KERN_ERR
|
||||
"rr_write: rejecting packet w/ bad xid\n");
|
||||
return -EINVAL;
|
||||
for (ret = 0; ret < MAX_REPLY_ROUTE; ret++)
|
||||
if (ept->rroute[ret].xid == rq->xid) {
|
||||
if (ept->rroute[ret].pid == 0xffffffff)
|
||||
continue;
|
||||
hdr.dst_pid = ept->rroute[ret].pid;
|
||||
hdr.dst_cid = ept->rroute[ret].cid;
|
||||
/* consume this reply */
|
||||
ept->rroute[ret].pid = 0xffffffff;
|
||||
goto found_rroute;
|
||||
}
|
||||
|
||||
hdr.dst_pid = ept->reply_pid;
|
||||
hdr.dst_cid = ept->reply_cid;
|
||||
|
||||
/* consume this reply */
|
||||
ept->reply_pid = 0xffffffff;
|
||||
printk(KERN_ERR "rr_write: rejecting packet w/ bad xid\n");
|
||||
return -EINVAL;
|
||||
|
||||
found_rroute:
|
||||
IO("REPLY on ept %p to xid=%d @ %d:%08x (%d bytes)\n",
|
||||
ept,
|
||||
be32_to_cpu(rq->xid), hdr.dst_pid, hdr.dst_cid, count);
|
||||
@ -854,56 +921,36 @@ int msm_rpc_write(struct msm_rpc_endpoint *ept, void *buffer, int count)
|
||||
hdr.version = RPCROUTER_VERSION;
|
||||
hdr.src_pid = ept->pid;
|
||||
hdr.src_cid = ept->cid;
|
||||
hdr.confirm_rx = 0;
|
||||
hdr.size = count + sizeof(uint32_t);
|
||||
|
||||
for (;;) {
|
||||
prepare_to_wait(&r_ept->quota_wait, &__wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
spin_lock_irqsave(&r_ept->quota_lock, flags);
|
||||
if (r_ept->tx_quota_cntr < RPCROUTER_DEFAULT_RX_QUOTA)
|
||||
break;
|
||||
if (signal_pending(current) &&
|
||||
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE)))
|
||||
break;
|
||||
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
|
||||
schedule();
|
||||
}
|
||||
finish_wait(&r_ept->quota_wait, &__wait);
|
||||
total = count;
|
||||
|
||||
if (signal_pending(current) &&
|
||||
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE))) {
|
||||
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
r_ept->tx_quota_cntr++;
|
||||
if (r_ept->tx_quota_cntr == RPCROUTER_DEFAULT_RX_QUOTA)
|
||||
hdr.confirm_rx = 1;
|
||||
mid = atomic_add_return(1, &next_mid) & 0xFF;
|
||||
|
||||
/* bump pacmark while interrupts disabled to avoid race
|
||||
* probably should be atomic op instead
|
||||
*/
|
||||
pacmark = PACMARK(count, ++next_pacmarkid, 0, 1);
|
||||
while (count > 0) {
|
||||
unsigned xfer;
|
||||
|
||||
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
|
||||
if (count > RPCROUTER_DATASIZE_MAX)
|
||||
xfer = RPCROUTER_DATASIZE_MAX;
|
||||
else
|
||||
xfer = count;
|
||||
|
||||
spin_lock_irqsave(&smd_lock, flags);
|
||||
hdr.confirm_rx = 0;
|
||||
hdr.size = xfer + sizeof(uint32_t);
|
||||
|
||||
needed = sizeof(hdr) + hdr.size;
|
||||
while (smd_write_avail(smd_channel) < needed) {
|
||||
spin_unlock_irqrestore(&smd_lock, flags);
|
||||
msleep(250);
|
||||
spin_lock_irqsave(&smd_lock, flags);
|
||||
/* total == count -> must be first packet
|
||||
* xfer == count -> must be last packet
|
||||
*/
|
||||
pacmark = PACMARK(xfer, mid, (total == count), (xfer == count));
|
||||
|
||||
ret = msm_rpc_write_pkt(ept, r_ept, &hdr, pacmark, buffer, xfer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
buffer += xfer;
|
||||
count -= xfer;
|
||||
}
|
||||
|
||||
/* TODO: deal with full fifo */
|
||||
smd_write(smd_channel, &hdr, sizeof(hdr));
|
||||
smd_write(smd_channel, &pacmark, sizeof(pacmark));
|
||||
smd_write(smd_channel, buffer, count);
|
||||
|
||||
spin_unlock_irqrestore(&smd_lock, flags);
|
||||
|
||||
return count;
|
||||
return total;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_rpc_write);
|
||||
|
||||
@ -1104,20 +1151,30 @@ int __msm_rpc_read(struct msm_rpc_endpoint *ept,
|
||||
|
||||
*frag_ret = pkt->first;
|
||||
rq = (void*) pkt->first->data;
|
||||
|
||||
if (((rq->prog&0xFFFFFFF0) == RMT_STORAGE_APIPROG_BE32) ||
|
||||
((rq->prog&0xFFFFFFF0) == RMT_STORAGE_SRV_APIPROG_BE32)) {
|
||||
printk(KERN_DEBUG
|
||||
"rpc_read: prog = %x , procedure = %d, type = %d, xid = %d\n"
|
||||
, be32_to_cpu(rq->prog), be32_to_cpu(rq->procedure)
|
||||
, be32_to_cpu(rq->type), be32_to_cpu(rq->xid));
|
||||
}
|
||||
|
||||
if ((rc >= (sizeof(uint32_t) * 3)) && (rq->type == 0)) {
|
||||
IO("READ on ept %p is a CALL on %08x:%08x proc %d xid %d\n",
|
||||
ept, be32_to_cpu(rq->prog), be32_to_cpu(rq->vers),
|
||||
be32_to_cpu(rq->procedure),
|
||||
be32_to_cpu(rq->xid));
|
||||
/* RPC CALL */
|
||||
if (ept->reply_pid != 0xffffffff) {
|
||||
if (ept->rroute[ept->next_rroute].pid != 0xffffffff) {
|
||||
printk(KERN_WARNING
|
||||
"rr_read: lost previous reply xid...\n");
|
||||
}
|
||||
/* TODO: locking? */
|
||||
ept->reply_pid = pkt->hdr.src_pid;
|
||||
ept->reply_cid = pkt->hdr.src_cid;
|
||||
ept->reply_xid = rq->xid;
|
||||
ept->rroute[ept->next_rroute].pid = pkt->hdr.src_pid;
|
||||
ept->rroute[ept->next_rroute].cid = pkt->hdr.src_cid;
|
||||
ept->rroute[ept->next_rroute].xid = rq->xid;
|
||||
ept->next_rroute = (ept->next_rroute + 1) & (MAX_REPLY_ROUTE - 1);
|
||||
}
|
||||
#if TRACE_RPC_MSG
|
||||
else if ((rc >= (sizeof(uint32_t) * 3)) && (rq->type == 1))
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define RPCROUTER_VERSION 1
|
||||
#define RPCROUTER_PROCESSORS_MAX 4
|
||||
#define RPCROUTER_MSGSIZE_MAX 512
|
||||
#define RPCROUTER_DATASIZE_MAX 500
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define RPCROUTER_PEND_REPLIES_MAX 32
|
||||
#endif
|
||||
@ -50,6 +51,7 @@
|
||||
#define RPCROUTER_CTRL_CMD_REMOVE_CLIENT 6
|
||||
#define RPCROUTER_CTRL_CMD_RESUME_TX 7
|
||||
#define RPCROUTER_CTRL_CMD_EXIT 8
|
||||
#define RPCROUTER_CTRL_CMD_PING 9
|
||||
|
||||
#define RPCROUTER_DEFAULT_RX_QUOTA 5
|
||||
|
||||
@ -141,6 +143,15 @@ struct rr_remote_endpoint {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct msm_reply_route {
|
||||
uint32_t xid;
|
||||
uint32_t pid;
|
||||
uint32_t cid;
|
||||
uint32_t unused;
|
||||
};
|
||||
|
||||
#define MAX_REPLY_ROUTE 4
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
struct msm_rpc_reply {
|
||||
struct list_head list;
|
||||
@ -183,15 +194,12 @@ struct msm_rpc_endpoint {
|
||||
uint32_t dst_prog; /* be32 */
|
||||
uint32_t dst_vers; /* be32 */
|
||||
|
||||
/* reply remote address
|
||||
* if reply_pid == 0xffffffff, none available
|
||||
* RPC_REPLY writes may only go to the pid/cid/xid of the
|
||||
* last RPC_CALL we received.
|
||||
/* RPC_REPLY writes must be routed to the pid/cid of the
|
||||
* RPC_CALL they are in reply to. Keep a cache of valid
|
||||
* xid/pid/cid groups. pid 0xffffffff -> not valid.
|
||||
*/
|
||||
uint32_t reply_pid;
|
||||
uint32_t reply_cid;
|
||||
uint32_t reply_xid; /* be32 */
|
||||
uint32_t next_pm; /* Pacmark sequence */
|
||||
unsigned next_rroute;
|
||||
struct msm_reply_route rroute[MAX_REPLY_ROUTE];
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
/* reply queue for inbound messages */
|
||||
@ -224,6 +232,7 @@ void msm_rpcrouter_exit_devices(void);
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
void get_requesting_client(struct msm_rpc_endpoint *ept, uint32_t xid,
|
||||
struct msm_rpc_client_info *clnt_info);
|
||||
int msm_rpc_clear_netreset(struct msm_rpc_endpoint *ept);
|
||||
#endif
|
||||
|
||||
extern dev_t msm_rpcrouter_devno;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/msm_rpcrouter.h>
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/cdev.h>
|
||||
|
@ -78,6 +78,8 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/msm_rpcrouter.h>
|
||||
|
||||
@ -421,7 +423,7 @@ int xdr_send_msg(struct msm_rpc_xdr *xdr)
|
||||
void xdr_init(struct msm_rpc_xdr *xdr)
|
||||
{
|
||||
mutex_init(&xdr->out_lock);
|
||||
mutex_init(&xdr->in_lock);
|
||||
init_waitqueue_head(&xdr->in_buf_wait_q);
|
||||
|
||||
xdr->in_buf = NULL;
|
||||
xdr->in_size = 0;
|
||||
@ -434,7 +436,7 @@ void xdr_init(struct msm_rpc_xdr *xdr)
|
||||
|
||||
void xdr_init_input(struct msm_rpc_xdr *xdr, void *buf, uint32_t size)
|
||||
{
|
||||
mutex_lock(&xdr->in_lock);
|
||||
wait_event(xdr->in_buf_wait_q, !(xdr->in_buf));
|
||||
|
||||
xdr->in_buf = buf;
|
||||
xdr->in_size = size;
|
||||
@ -455,7 +457,7 @@ void xdr_clean_input(struct msm_rpc_xdr *xdr)
|
||||
xdr->in_size = 0;
|
||||
xdr->in_index = 0;
|
||||
|
||||
mutex_unlock(&xdr->in_lock);
|
||||
wake_up(&xdr->in_buf_wait_q);
|
||||
}
|
||||
|
||||
void xdr_clean_output(struct msm_rpc_xdr *xdr)
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "board-htcleo.h"
|
||||
|
||||
#define MAX_SMD_TTYS 32
|
||||
#define MAX_TTY_BUF_SIZE 2048
|
||||
|
||||
static DEFINE_MUTEX(smd_tty_lock);
|
||||
|
||||
@ -75,6 +76,9 @@ static void smd_tty_work_func(struct work_struct *work)
|
||||
tty->low_latency = 0;
|
||||
tty_flip_buffer_push(tty);
|
||||
break;
|
||||
if (avail > MAX_TTY_BUF_SIZE)
|
||||
avail = MAX_TTY_BUF_SIZE;
|
||||
|
||||
}
|
||||
|
||||
ptr = NULL;
|
||||
|
@ -169,18 +169,10 @@ static int msm_timer_set_next_event(unsigned long cycles,
|
||||
clock->last_set = now;
|
||||
clock->alarm_vtime = alarm + clock->offset;
|
||||
late = now - alarm;
|
||||
if (late >= (int)(-clock->write_delay << clock->shift) && late < DGT_HZ*5) {
|
||||
static int print_limit = 10;
|
||||
if (print_limit > 0) {
|
||||
print_limit--;
|
||||
printk(KERN_NOTICE "msm_timer_set_next_event(%lu) "
|
||||
"clock %s, alarm already expired, now %x, "
|
||||
"alarm %x, late %d%s\n",
|
||||
cycles, clock->clockevent.name, now, alarm, late,
|
||||
print_limit ? "" : " stop printing");
|
||||
}
|
||||
if (late >= (int)(-clock->write_delay << clock->shift) &&
|
||||
late < clock->freq*5)
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -582,9 +574,12 @@ static struct msm_clock msm_clocks[] = {
|
||||
#endif
|
||||
.freq = GPT_HZ,
|
||||
.flags =
|
||||
#ifdef CONFIG_ARCH_MSM_ARM11
|
||||
MSM_CLOCK_FLAGS_UNSTABLE_COUNT |
|
||||
MSM_CLOCK_FLAGS_ODD_MATCH_WRITE |
|
||||
MSM_CLOCK_FLAGS_DELAYED_WRITE_POST,
|
||||
MSM_CLOCK_FLAGS_DELAYED_WRITE_POST |
|
||||
#endif
|
||||
0,
|
||||
.write_delay = 9,
|
||||
},
|
||||
[MSM_CLOCK_DGT] = {
|
||||
|
2
drivers/misc/pmem.c
Normal file → Executable file
2
drivers/misc/pmem.c
Normal file → Executable file
@ -4386,4 +4386,4 @@ static void __exit pmem_exit(void)
|
||||
module_init(pmem_init);
|
||||
module_exit(pmem_exit);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -33,12 +33,15 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
unsigned crci_mask;
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define MSM_NAND_BASE 0xA0200000
|
||||
#else
|
||||
@ -178,6 +181,11 @@ static void *msm_nand_get_dma_buffer(struct msm_nand_chip *chip, size_t size)
|
||||
do {
|
||||
free_index = __ffs(free_bitmask);
|
||||
current_need_mask = need_mask << free_index;
|
||||
|
||||
if (size + free_index * MSM_NAND_DMA_BUFFER_SLOTS >=
|
||||
MSM_NAND_DMA_BUFFER_SIZE)
|
||||
return NULL;
|
||||
|
||||
if ((bitmask & current_need_mask) == 0) {
|
||||
old_bitmask =
|
||||
atomic_cmpxchg(&chip->dma_buffer_busy,
|
||||
@ -262,7 +270,7 @@ uint32_t flash_read_id(struct msm_nand_chip *chip)
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(
|
||||
chip->dma_channel, DMOV_CMD_PTR_LIST |
|
||||
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
|
||||
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
@ -306,7 +314,7 @@ int flash_read_config(struct msm_nand_chip *chip)
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(
|
||||
chip->dma_channel, DMOV_CMD_PTR_LIST |
|
||||
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
|
||||
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
@ -346,7 +354,7 @@ unsigned flash_rd_reg(struct msm_nand_chip *chip, unsigned addr)
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(
|
||||
chip->dma_channel, DMOV_CMD_PTR_LIST |
|
||||
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
|
||||
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
rv = dma_buffer->data;
|
||||
@ -379,7 +387,7 @@ void flash_wr_reg(struct msm_nand_chip *chip, unsigned addr, unsigned val)
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(
|
||||
chip->dma_channel, DMOV_CMD_PTR_LIST |
|
||||
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
|
||||
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
@ -750,7 +758,7 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_o
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(
|
||||
chip->dma_channel, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(
|
||||
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(
|
||||
msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
@ -893,13 +901,13 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_o
|
||||
dma_buffer->data.result[2].buffer_status,
|
||||
dma_buffer->data.result[3].flash_status,
|
||||
dma_buffer->data.result[3].buffer_status,
|
||||
dma_buffer->data.result[4].flash_status,
|
||||
dma_buffer->data.result[4].buffer_status,
|
||||
dma_buffer->data.result[4].buffer_status,
|
||||
dma_buffer->data.result[5].buffer_status,
|
||||
dma_buffer->data.result[5].flash_status,
|
||||
dma_buffer->data.result[5].buffer_status,
|
||||
dma_buffer->data.result[6].flash_status,
|
||||
dma_buffer->data.result[6].buffer_status,
|
||||
dma_buffer->data.result[6].buffer_status,
|
||||
dma_buffer->data.result[7].buffer_status,
|
||||
dma_buffer->data.result[7].flash_status,
|
||||
dma_buffer->data.result[7].buffer_status);
|
||||
}
|
||||
#endif
|
||||
@ -1364,7 +1372,7 @@ msm_nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
|
||||
dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) | CMD_PTR_LP;
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
msm_dmov_exec_cmd(chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
/* if any of the writes failed (0x10), or there was a
|
||||
@ -1576,7 +1584,7 @@ msm_nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(
|
||||
chip->dma_channel, DMOV_CMD_PTR_LIST |
|
||||
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
|
||||
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
@ -1727,7 +1735,7 @@ msm_nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
|
||||
dma_buffer->cmd) >> 3) | CMD_PTR_LP;
|
||||
|
||||
dsb();
|
||||
msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST |
|
||||
msm_dmov_exec_cmd(chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
|
||||
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
|
||||
dsb();
|
||||
|
||||
|
@ -697,9 +697,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
int fbidx = iminor(inode);
|
||||
struct fb_info *info = registered_fb[fbidx];
|
||||
u32 *buffer, *dst;
|
||||
u32 __iomem *src;
|
||||
int c, i, cnt = 0, err = 0;
|
||||
u8 *buffer, *dst;
|
||||
u8 __iomem *src;
|
||||
int c, cnt = 0, err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info || ! info->screen_base)
|
||||
@ -730,7 +730,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
src = (u32 __iomem *) (info->screen_base + p);
|
||||
src = (u8 __iomem *) (info->screen_base + p);
|
||||
|
||||
if (info->fbops->fb_sync)
|
||||
info->fbops->fb_sync(info);
|
||||
@ -738,17 +738,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
while (count) {
|
||||
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
|
||||
dst = buffer;
|
||||
for (i = c >> 2; i--; )
|
||||
*dst++ = fb_readl(src++);
|
||||
if (c & 3) {
|
||||
u8 *dst8 = (u8 *) dst;
|
||||
u8 __iomem *src8 = (u8 __iomem *) src;
|
||||
|
||||
for (i = c & 3; i--;)
|
||||
*dst8++ = fb_readb(src8++);
|
||||
|
||||
src = (u32 __iomem *) src8;
|
||||
}
|
||||
fb_memcpy_fromfb(dst, src, c);
|
||||
dst += c;
|
||||
src += c;
|
||||
|
||||
if (copy_to_user(buf, buffer, c)) {
|
||||
err = -EFAULT;
|
||||
@ -772,9 +764,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
int fbidx = iminor(inode);
|
||||
struct fb_info *info = registered_fb[fbidx];
|
||||
u32 *buffer, *src;
|
||||
u32 __iomem *dst;
|
||||
int c, i, cnt = 0, err = 0;
|
||||
u8 *buffer, *src;
|
||||
u8 __iomem *dst;
|
||||
int c, cnt = 0, err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info || !info->screen_base)
|
||||
@ -811,7 +803,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
dst = (u32 __iomem *) (info->screen_base + p);
|
||||
dst = (u8 __iomem *) (info->screen_base + p);
|
||||
|
||||
if (info->fbops->fb_sync)
|
||||
info->fbops->fb_sync(info);
|
||||
@ -825,19 +817,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = c >> 2; i--; )
|
||||
fb_writel(*src++, dst++);
|
||||
|
||||
if (c & 3) {
|
||||
u8 *src8 = (u8 *) src;
|
||||
u8 __iomem *dst8 = (u8 __iomem *) dst;
|
||||
|
||||
for (i = c & 3; i--; )
|
||||
fb_writeb(*src8++, dst8++);
|
||||
|
||||
dst = (u32 __iomem *) dst8;
|
||||
}
|
||||
|
||||
fb_memcpy_tofb(dst, src, c);
|
||||
dst += c;
|
||||
src += c;
|
||||
*ppos += c;
|
||||
buf += c;
|
||||
cnt += c;
|
||||
@ -877,13 +859,13 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
|
||||
|
||||
if ((err = info->fbops->fb_pan_display(var, info)))
|
||||
return err;
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
if (var->vmode & FB_VMODE_YWRAP)
|
||||
info->var.vmode |= FB_VMODE_YWRAP;
|
||||
else
|
||||
info->var.vmode &= ~FB_VMODE_YWRAP;
|
||||
return 0;
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
if (var->vmode & FB_VMODE_YWRAP)
|
||||
info->var.vmode |= FB_VMODE_YWRAP;
|
||||
else
|
||||
info->var.vmode &= ~FB_VMODE_YWRAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
|
||||
@ -1438,6 +1420,7 @@ static const struct file_operations fb_fops = {
|
||||
#ifdef CONFIG_FB_DEFERRED_IO
|
||||
.fsync = fb_deferred_io_fsync,
|
||||
#endif
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
struct class *fb_class;
|
||||
@ -1468,16 +1451,70 @@ static int fb_check_foreignness(struct fb_info *fi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw)
|
||||
static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
|
||||
{
|
||||
/* is the generic aperture base the same as the HW one */
|
||||
if (gen->aperture_base == hw->aperture_base)
|
||||
if (gen->base == hw->base)
|
||||
return true;
|
||||
/* is the generic aperture base inside the hw base->hw base+size */
|
||||
if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size)
|
||||
if (gen->base > hw->base && gen->base < hw->base + hw->size)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool fb_do_apertures_overlap(struct apertures_struct *gena,
|
||||
struct apertures_struct *hwa)
|
||||
{
|
||||
int i, j;
|
||||
if (!hwa || !gena)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < hwa->count; ++i) {
|
||||
struct aperture *h = &hwa->ranges[i];
|
||||
for (j = 0; j < gena->count; ++j) {
|
||||
struct aperture *g = &gena->ranges[j];
|
||||
printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
|
||||
(unsigned long long)g->base,
|
||||
(unsigned long long)g->size,
|
||||
(unsigned long long)h->base,
|
||||
(unsigned long long)h->size);
|
||||
if (apertures_overlap(g, h))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define VGA_FB_PHYS 0xA0000
|
||||
void remove_conflicting_framebuffers(struct apertures_struct *a,
|
||||
const char *name, bool primary)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* check all firmware fbs and kick off if the base addr overlaps */
|
||||
for (i = 0 ; i < FB_MAX; i++) {
|
||||
struct apertures_struct *gen_aper;
|
||||
if (!registered_fb[i])
|
||||
continue;
|
||||
|
||||
if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
|
||||
continue;
|
||||
|
||||
gen_aper = registered_fb[i]->apertures;
|
||||
if (fb_do_apertures_overlap(gen_aper, a) ||
|
||||
(primary && gen_aper && gen_aper->count &&
|
||||
gen_aper->ranges[0].base == VGA_FB_PHYS)) {
|
||||
|
||||
printk(KERN_ERR "fb: conflicting fb hw usage "
|
||||
"%s vs %s - removing generic driver\n",
|
||||
name, registered_fb[i]->fix.id);
|
||||
unregister_framebuffer(registered_fb[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(remove_conflicting_framebuffers);
|
||||
|
||||
/**
|
||||
* register_framebuffer - registers a frame buffer device
|
||||
* @fb_info: frame buffer info structure
|
||||
|
75
drivers/video/msm/Kconfig
Normal file → Executable file
75
drivers/video/msm/Kconfig
Normal file → Executable file
@ -1,3 +1,26 @@
|
||||
config FB_MSM
|
||||
tristate "MSM Framebuffer"
|
||||
depends on FB && ARCH_MSM
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
default y
|
||||
|
||||
config FB_MSM_MDP_PPP
|
||||
bool "MSM MDP PPP"
|
||||
depends on FB_MSM_LEGACY_MDP
|
||||
default y
|
||||
|
||||
config FB_MSM_LCDC
|
||||
bool "Support for integrated LCD controller in MDP3/4"
|
||||
depends on FB_MSM && (MSM_MDP31 || MSM_MDP302 || MSM_MDP40)
|
||||
default y
|
||||
|
||||
config FB_MSM_MDDI
|
||||
bool "Support for MSM MDDI controllers"
|
||||
depends on FB_MSM
|
||||
default y
|
||||
|
||||
config FB_MSM
|
||||
tristate
|
||||
depends on FB && ARCH_MSM
|
||||
@ -6,43 +29,35 @@ config FB_MSM
|
||||
select FB_CFB_IMAGEBLIT
|
||||
default y
|
||||
|
||||
config FB_MSM_LEGACY_MDP
|
||||
bool "MSM Legacy MDP (qsd8k)"
|
||||
depends on FB_MSM && (MSM_MDP30 || MSM_MDP31 || MSM_MDP302)
|
||||
default y
|
||||
|
||||
config FB_MSM_MDP_PPP
|
||||
bool "MSM MDP PPP"
|
||||
depends on FB_MSM_LEGACY_MDP
|
||||
default y
|
||||
|
||||
config FB_MSM_LCDC
|
||||
bool "Support for integrated LCD controller in qsd8x50 and MSM7x27"
|
||||
depends on FB_MSM && (MSM_MDP31 || MSM_MDP302)
|
||||
bool "Support for integrated LCD controller in qsd8x50 ,MSM7x27 and MSM7x30"
|
||||
depends on FB_MSM && (MSM_MDP31 || MSM_MDP302 || MSM_MDP40)
|
||||
default y
|
||||
|
||||
config FB_MSM_TVOUT
|
||||
bool "Support for TV-Out in qsd8x50"
|
||||
depends on FB_MSM && MSM_MDP31
|
||||
default n
|
||||
|
||||
config FB_MSM_OVERLAY
|
||||
bool "Support for overlay in MSM7X30"
|
||||
depends on FB_MSM && MSM_MDP40
|
||||
config FB_MSM_MDDI
|
||||
bool "Support for MSM MDDI controllers"
|
||||
depends on FB_MSM
|
||||
default y
|
||||
|
||||
config FB_MSM_DTV
|
||||
depends on FB_MSM_OVERLAY
|
||||
bool
|
||||
config FB_MSM_MDDI_EPSON
|
||||
bool "Support for Epson MDDI panels"
|
||||
depends on FB_MSM_MDDI
|
||||
default n
|
||||
|
||||
config MSM_ROTATOR
|
||||
tristate "MSM Offline Image Rotator Driver"
|
||||
depends on ARCH_MSM7X30 && ANDROID_PMEM
|
||||
default y
|
||||
help
|
||||
This driver provides support for the image rotator HW block in the
|
||||
MSM 7x30 SoC.
|
||||
|
||||
config MSM_ROTATOR_USE_IMEM
|
||||
bool "Enable rotator driver to use iMem"
|
||||
depends on MSM_ROTATOR
|
||||
default y
|
||||
help
|
||||
This option enables the msm_rotator driver to use the move efficient
|
||||
iMem. Some MSM platforms may not have iMem available for the rotator
|
||||
block. Or some systems may want the iMem to be dedicated to a
|
||||
different function.
|
||||
config FB_MSM_MDDI_NOVTEC
|
||||
bool "Support for Novtec MDDI panels"
|
||||
depends on FB_MSM_MDDI
|
||||
default n
|
||||
|
||||
config MSM_HDMI
|
||||
bool "Support for HDMI in QCT platform"
|
||||
|
7
drivers/video/msm/Makefile
Normal file → Executable file
7
drivers/video/msm/Makefile
Normal file → Executable file
@ -14,6 +14,8 @@ obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_overlay.o
|
||||
obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_overlay_mddi.o
|
||||
obj-$(CONFIG_MSM_MDP40) += msm_rotator.o
|
||||
|
||||
obj-$(CONFIG_FB_MSM_LEGACY_MDP) += mdp_hw_legacy.o
|
||||
|
||||
obj-$(CONFIG_MSM_MDP22) += mdp_ppp22.o
|
||||
obj-$(CONFIG_MSM_MDP30) += mdp_ppp22.o
|
||||
obj-$(CONFIG_MSM_MDP302)+= mdp_ppp22.o
|
||||
@ -25,11 +27,10 @@ obj-y += mddi.o
|
||||
|
||||
# MDDI client/panel drivers
|
||||
#
|
||||
obj-y += mddi_client_dummy.o
|
||||
obj-y += mddi_client_simple.o
|
||||
obj-y += mddi_client_toshiba.o
|
||||
obj-y += mddi_client_epson.o
|
||||
obj-y += mddi_client_novb9f6_5582.o
|
||||
|
||||
# MDP LCD controller driver
|
||||
obj-$(CONFIG_FB_MSM_LCDC) += mdp_lcdc.o
|
||||
obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o tvfb.o
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/earlysuspend.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <mach/msm_fb.h>
|
||||
#include "mddi_hw.h"
|
||||
|
||||
@ -106,7 +106,9 @@ struct mddi_info {
|
||||
};
|
||||
|
||||
static void mddi_init_rev_encap(struct mddi_info *mddi);
|
||||
/* FIXME: Workaround for Novatek
|
||||
static void mddi_skew_calibration(struct mddi_info *mddi);
|
||||
*/
|
||||
|
||||
#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
|
||||
#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
|
||||
@ -204,10 +206,8 @@ static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
|
||||
|
||||
static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
|
||||
{
|
||||
union mddi_rev *rev = mddi->rev_data;
|
||||
uint32_t rev_data_count;
|
||||
uint32_t rev_crc_err_count;
|
||||
int i;
|
||||
struct reg_read_info *ri;
|
||||
size_t prev_offset;
|
||||
uint16_t length;
|
||||
@ -242,6 +242,8 @@ static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
|
||||
return;
|
||||
|
||||
if (mddi_debug_flags & 1) {
|
||||
int i;
|
||||
union mddi_rev *rev = mddi->rev_data;
|
||||
printk(KERN_INFO "INT %x, STAT %x, CURR_REV_PTR %x\n",
|
||||
mddi_readl(INT), mddi_readl(STAT),
|
||||
mddi_readl(CURR_REV_PTR));
|
||||
@ -355,7 +357,7 @@ static irqreturn_t mddi_isr(int irq, void *data)
|
||||
static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
|
||||
uint32_t intmask, int timeout)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
spin_lock_irqsave(&mddi->int_lock, irq_flags);
|
||||
mddi->got_int &= ~intmask;
|
||||
@ -369,7 +371,7 @@ static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
|
||||
static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
|
||||
{
|
||||
if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
|
||||
printk(KERN_INFO KERN_ERR "mddi_wait_interrupt %d, timeout "
|
||||
printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
|
||||
"waiting for %x, INT = %x, STAT = %x gotint = %x\n",
|
||||
current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
|
||||
mddi->got_int);
|
||||
@ -399,7 +401,10 @@ static uint16_t mddi_init_registers(struct mddi_info *mddi)
|
||||
mddi_writel(0x0001, VERSION);
|
||||
mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
|
||||
mddi_writel(0x0003, SPM); /* subframes per media */
|
||||
mddi_writel(0x0005, TA1_LEN);
|
||||
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
|
||||
mddi_writel(0x00C8, TA1_LEN);
|
||||
else
|
||||
mddi_writel(0x0005, TA1_LEN);
|
||||
mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
|
||||
mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
|
||||
mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
|
||||
@ -431,7 +436,7 @@ static uint16_t mddi_init_registers(struct mddi_info *mddi)
|
||||
mddi_writel(0x0050, DRIVE_LO);
|
||||
mddi_writel(0x00320000, PAD_IO_CTL);
|
||||
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
|
||||
mddi_writel(0x40884020, PAD_CAL);
|
||||
mddi_writel(0x40880020, PAD_CAL);
|
||||
else
|
||||
mddi_writel(0x00220020, PAD_CAL);
|
||||
#else
|
||||
@ -469,7 +474,7 @@ static void mddi_suspend(struct msm_mddi_client_data *cdata)
|
||||
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
|
||||
/* turn off the clock */
|
||||
clk_disable(mddi->clk);
|
||||
#if CONFIG_MSM_MDP40
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
clk_disable(mdp_clk);
|
||||
#endif
|
||||
wake_unlock(&mddi->idle_lock);
|
||||
@ -484,7 +489,7 @@ static void mddi_resume(struct msm_mddi_client_data *cdata)
|
||||
/* turn on the client */
|
||||
if (mddi->power_client)
|
||||
mddi->power_client(&mddi->client_data, 1);
|
||||
#if CONFIG_MSM_MDP40
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
clk_enable(mdp_clk);
|
||||
#endif
|
||||
/* turn on the clock */
|
||||
@ -498,7 +503,8 @@ static void mddi_resume(struct msm_mddi_client_data *cdata)
|
||||
*/
|
||||
mddi_writel(mddi->int_enable, INTEN);
|
||||
mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
|
||||
mddi_writel(MDDI_CMD_SEND_RTD, CMD);
|
||||
if (mddi->type == MSM_MDP_MDDI_TYPE_I)
|
||||
mddi_writel(MDDI_CMD_SEND_RTD, CMD);
|
||||
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
|
||||
mddi_set_auto_hibernate(&mddi->client_data, 1);
|
||||
wake_unlock(&mddi->idle_lock);
|
||||
@ -689,7 +695,7 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
|
||||
struct reg_read_info ri;
|
||||
unsigned s;
|
||||
int retry_count = 2;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
mutex_lock(&mddi->reg_read_lock);
|
||||
|
||||
@ -720,6 +726,9 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
|
||||
|
||||
do {
|
||||
init_completion(&ri.done);
|
||||
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
|
||||
mddi_set_auto_hibernate(&mddi->client_data, 0);
|
||||
mddi_writel(MDDI_CMD_SEND_RTD, CMD);
|
||||
mddi->reg_read = &ri;
|
||||
mddi_writel(mddi->reg_read_addr, PRI_PTR);
|
||||
|
||||
@ -732,10 +741,14 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
|
||||
/* while((s & MDDI_STAT_PRI_LINK_LIST_DONE) == 0){ */
|
||||
/* s = mddi_readl(STAT); */
|
||||
/* } */
|
||||
|
||||
/* Enable Periodic Reverse Encapsulation. */
|
||||
mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
|
||||
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
|
||||
if (mddi->type == MSM_MDP_MDDI_TYPE_II) {
|
||||
mddi_writel(MDDI_CMD_SEND_REV_ENCAP, CMD);
|
||||
mddi_wait_interrupt(mddi, MDDI_INT_REV_DATA_AVAIL);
|
||||
} else {
|
||||
/* Enable Periodic Reverse Encapsulation. */
|
||||
mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
|
||||
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
|
||||
}
|
||||
if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
|
||||
!ri.done.done) {
|
||||
printk(KERN_INFO "mddi_remote_read(%x) timeout "
|
||||
@ -763,6 +776,8 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
|
||||
"MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
|
||||
"curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
|
||||
mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
|
||||
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
|
||||
mddi_set_auto_hibernate(&mddi->client_data, 1);
|
||||
} while (retry_count-- > 0);
|
||||
/* Disable Periodic Reverse Encapsulation. */
|
||||
mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
|
||||
@ -830,7 +845,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi)
|
||||
sizeof(*mddi->reg_write_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Workaround for Novatek
|
||||
static void mddi_skew_calibration(struct mddi_info *mddi)
|
||||
{
|
||||
struct msm_mddi_platform_data *pdata = mddi->client_pdev.dev.platform_data;
|
||||
@ -842,6 +857,7 @@ static void mddi_skew_calibration(struct mddi_info *mddi)
|
||||
clk_set_rate( mddi->clk, pdata->clk_rate);
|
||||
mdelay(1);
|
||||
}
|
||||
*/
|
||||
|
||||
static int __init mddi_probe(struct platform_device *pdev)
|
||||
{
|
||||
@ -871,7 +887,7 @@ static int __init mddi_probe(struct platform_device *pdev)
|
||||
printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
|
||||
mddi->irq);
|
||||
mddi->power_client = pdata->power_client;
|
||||
if (pdata->type != NULL)
|
||||
if ((pdata->type != NULL) && (pdata->type != MSM_MDP_MDDI_TYPE_I))
|
||||
mddi->type = pdata->type;
|
||||
|
||||
mutex_init(&mddi->reg_write_lock);
|
||||
|
@ -1,97 +0,0 @@
|
||||
/* drivers/video/msm_fb/mddi_client_dummy.c
|
||||
*
|
||||
* Support for "dummy" mddi client devices which require no
|
||||
* special initialization code.
|
||||
*
|
||||
* Copyright (C) 2007 Google Incorporated
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/msm_fb.h>
|
||||
|
||||
struct panel_info {
|
||||
struct platform_device pdev;
|
||||
struct msm_panel_data panel_data;
|
||||
};
|
||||
|
||||
static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mddi_dummy_resume(struct msm_panel_data *panel_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mddi_dummy_blank(struct msm_panel_data *panel_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mddi_dummy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
|
||||
struct panel_info *panel =
|
||||
kzalloc(sizeof(struct panel_info), GFP_KERNEL);
|
||||
int ret;
|
||||
if (!panel)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, panel);
|
||||
panel->panel_data.suspend = mddi_dummy_suspend;
|
||||
panel->panel_data.resume = mddi_dummy_resume;
|
||||
panel->panel_data.blank = mddi_dummy_blank;
|
||||
panel->panel_data.unblank = mddi_dummy_unblank;
|
||||
panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
|
||||
panel->pdev.name = "msm_panel";
|
||||
panel->pdev.id = pdev->id;
|
||||
platform_device_add_resources(&panel->pdev,
|
||||
client_data->fb_resource, 1);
|
||||
panel->panel_data.fb_data = client_data->private_client_data;
|
||||
panel->pdev.dev.platform_data = &panel->panel_data;
|
||||
ret = platform_device_register(&panel->pdev);
|
||||
if (ret) {
|
||||
kfree(panel);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mddi_dummy_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct panel_info *panel = platform_get_drvdata(pdev);
|
||||
kfree(panel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mddi_client_dummy = {
|
||||
.probe = mddi_dummy_probe,
|
||||
.remove = mddi_dummy_remove,
|
||||
.driver = { .name = "mddi_c_dummy" },
|
||||
};
|
||||
|
||||
static int __init mddi_client_dummy_init(void)
|
||||
{
|
||||
platform_driver_register(&mddi_client_dummy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(mddi_client_dummy_init);
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <mach/msm_fb.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(epson_vsync_wait);
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <mach/msm_fb.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(novtec_vsync_wait);
|
||||
|
||||
@ -145,7 +147,6 @@ static irqreturn_t novtec_vsync_interrupt(int irq, void *data)
|
||||
|
||||
panel->novtec_got_int = 1;
|
||||
if (panel->novtec_callback) {
|
||||
mdelay(3);
|
||||
panel->novtec_callback->func(panel->novtec_callback);
|
||||
panel->novtec_callback = 0;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/msm_fb.h>
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
|
||||
|
236
drivers/video/msm/mddi_client_simple.c
Normal file
236
drivers/video/msm/mddi_client_simple.c
Normal file
@ -0,0 +1,236 @@
|
||||
/* drivers/video/msm_fb/mddi_client_simple.c
|
||||
*
|
||||
* Support for simple mddi client devices which require no special
|
||||
* initialization code except for what may be provided in the board file.
|
||||
* If the clients do not provide board specific code, this driver's
|
||||
* panel operations are no-ops.
|
||||
*
|
||||
* Copyright (C) 2007-2010, Google Incorporated
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <mach/msm_fb.h>
|
||||
|
||||
struct panel_info {
|
||||
struct platform_device pdev;
|
||||
struct msm_mddi_client_data *client_data;
|
||||
struct msm_panel_data panel_data;
|
||||
struct msmfb_callback *fb_callback;
|
||||
wait_queue_head_t vsync_wait;
|
||||
int got_vsync;
|
||||
int irq;
|
||||
};
|
||||
|
||||
#define to_panel_info(pd) container_of((pd), struct panel_info, panel_data)
|
||||
|
||||
static void mddi_simple_request_vsync(struct msm_panel_data *panel_data,
|
||||
struct msmfb_callback *callback)
|
||||
{
|
||||
struct panel_info *panel = to_panel_info(panel_data);
|
||||
struct msm_mddi_client_data *client_data = panel->client_data;
|
||||
|
||||
panel->fb_callback = callback;
|
||||
if (panel->got_vsync) {
|
||||
panel->got_vsync = 0;
|
||||
client_data->activate_link(client_data); /* clears interrupt */
|
||||
}
|
||||
}
|
||||
|
||||
static void mddi_simple_wait_vsync(struct msm_panel_data *panel_data)
|
||||
{
|
||||
struct panel_info *panel = to_panel_info(panel_data);
|
||||
struct msm_mddi_client_data *client_data = panel->client_data;
|
||||
int ret;
|
||||
|
||||
if (panel->got_vsync) {
|
||||
panel->got_vsync = 0;
|
||||
client_data->activate_link(client_data); /* clears interrupt */
|
||||
}
|
||||
|
||||
ret = wait_event_timeout(panel->vsync_wait, panel->got_vsync, HZ/2);
|
||||
if (!ret && !panel->got_vsync)
|
||||
pr_err("mddi_client_simple: timeout waiting for vsync\n");
|
||||
|
||||
panel->got_vsync = 0;
|
||||
/* interrupt clears when screen dma starts */
|
||||
}
|
||||
|
||||
|
||||
static int mddi_simple_suspend(struct msm_panel_data *panel_data)
|
||||
{
|
||||
struct panel_info *panel = to_panel_info(panel_data);
|
||||
struct msm_mddi_client_data *client_data = panel->client_data;
|
||||
struct msm_mddi_bridge_platform_data *bridge_data =
|
||||
client_data->private_client_data;
|
||||
int ret;
|
||||
|
||||
if (!bridge_data->uninit)
|
||||
return 0;
|
||||
|
||||
ret = bridge_data->uninit(bridge_data, client_data);
|
||||
if (ret) {
|
||||
pr_info("%s: non zero return from uninit\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
client_data->suspend(client_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mddi_simple_resume(struct msm_panel_data *panel_data)
|
||||
{
|
||||
struct panel_info *panel = to_panel_info(panel_data);
|
||||
struct msm_mddi_client_data *client_data = panel->client_data;
|
||||
struct msm_mddi_bridge_platform_data *bridge_data =
|
||||
client_data->private_client_data;
|
||||
|
||||
if (!bridge_data->init)
|
||||
return 0;
|
||||
|
||||
client_data->resume(client_data);
|
||||
return bridge_data->init(bridge_data, client_data);
|
||||
}
|
||||
|
||||
static int mddi_simple_blank(struct msm_panel_data *panel_data)
|
||||
{
|
||||
struct panel_info *panel = to_panel_info(panel_data);
|
||||
struct msm_mddi_client_data *client_data = panel->client_data;
|
||||
struct msm_mddi_bridge_platform_data *bridge_data =
|
||||
client_data->private_client_data;
|
||||
|
||||
if (!bridge_data->blank)
|
||||
return 0;
|
||||
return bridge_data->blank(bridge_data, client_data);
|
||||
}
|
||||
|
||||
static int mddi_simple_unblank(struct msm_panel_data *panel_data)
|
||||
{
|
||||
struct panel_info *panel = to_panel_info(panel_data);
|
||||
struct msm_mddi_client_data *client_data = panel->client_data;
|
||||
struct msm_mddi_bridge_platform_data *bridge_data =
|
||||
client_data->private_client_data;
|
||||
|
||||
if (!bridge_data->unblank)
|
||||
return 0;
|
||||
return bridge_data->unblank(bridge_data, client_data);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_vsync_irq(int irq, void *data)
|
||||
{
|
||||
struct panel_info *panel = data;
|
||||
|
||||
panel->got_vsync = 1;
|
||||
if (panel->fb_callback) {
|
||||
panel->fb_callback->func(panel->fb_callback);
|
||||
panel->fb_callback = NULL;
|
||||
}
|
||||
|
||||
wake_up(&panel->vsync_wait);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int mddi_simple_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
|
||||
struct msm_mddi_bridge_platform_data *bridge_data =
|
||||
client_data->private_client_data;
|
||||
struct panel_info *panel;
|
||||
int ret;
|
||||
|
||||
pr_debug("%s()\n", __func__);
|
||||
|
||||
panel = kzalloc(sizeof(struct panel_info), GFP_KERNEL);
|
||||
if (!panel)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, panel);
|
||||
|
||||
init_waitqueue_head(&panel->vsync_wait);
|
||||
|
||||
panel->irq = platform_get_irq_byname(pdev, "vsync");
|
||||
if (panel->irq >= 0) {
|
||||
ret = request_irq(panel->irq, handle_vsync_irq,
|
||||
IRQF_TRIGGER_RISING, "mddi_c_simple_vsync",
|
||||
panel);
|
||||
if (ret) {
|
||||
pr_err("%s: request vsync irq %d failed (%d)\n",
|
||||
__func__, panel->irq, ret);
|
||||
goto err_req_irq;
|
||||
}
|
||||
|
||||
panel->panel_data.wait_vsync = mddi_simple_wait_vsync;
|
||||
panel->panel_data.request_vsync = mddi_simple_request_vsync;
|
||||
}
|
||||
|
||||
panel->client_data = client_data;
|
||||
panel->panel_data.suspend = mddi_simple_suspend;
|
||||
panel->panel_data.resume = mddi_simple_resume;
|
||||
panel->panel_data.blank = mddi_simple_blank;
|
||||
panel->panel_data.unblank = mddi_simple_unblank;
|
||||
panel->panel_data.caps = bridge_data->caps;
|
||||
panel->panel_data.fb_data = &bridge_data->fb_data;
|
||||
|
||||
panel->pdev.name = "msm_panel";
|
||||
panel->pdev.id = pdev->id;
|
||||
platform_device_add_resources(&panel->pdev,
|
||||
client_data->fb_resource, 1);
|
||||
panel->pdev.dev.platform_data = &panel->panel_data;
|
||||
|
||||
if (bridge_data->init)
|
||||
bridge_data->init(bridge_data, client_data);
|
||||
|
||||
ret = platform_device_register(&panel->pdev);
|
||||
if (ret) {
|
||||
pr_err("%s: Can't register platform device\n", __func__);
|
||||
goto err_plat_dev_reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_plat_dev_reg:
|
||||
if (panel->irq >= 0)
|
||||
free_irq(panel->irq, panel);
|
||||
err_req_irq:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mddi_simple_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct panel_info *panel = platform_get_drvdata(pdev);
|
||||
kfree(panel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mddi_client_simple = {
|
||||
.probe = mddi_simple_probe,
|
||||
.remove = mddi_simple_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "mddi_c_simple"
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mddi_client_simple_init(void)
|
||||
{
|
||||
platform_driver_register(&mddi_client_simple);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(mddi_client_simple_init);
|
@ -21,6 +21,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/msm_fb.h>
|
||||
|
||||
|
||||
|
@ -53,8 +53,9 @@
|
||||
#define MDDI_MF_CNT 0x0084
|
||||
#define MDDI_CURR_REV_PTR 0x0088
|
||||
#define MDDI_CORE_VER 0x008c
|
||||
#define MDDI_PAD_IO_CTL 0x00a0
|
||||
#define MDDI_PAD_CAL 0x00a4
|
||||
#define MDDI_SF_LEN_CTL_REG 0x0094
|
||||
#define MDDI_PAD_IO_CTL 0x00a0
|
||||
#define MDDI_PAD_CAL 0x00a4
|
||||
|
||||
#define MDDI_INT_PRI_PTR_READ 0x0001
|
||||
#define MDDI_INT_SEC_PTR_READ 0x0002
|
||||
@ -131,8 +132,10 @@
|
||||
#define MDDI_HOST_TA2_LEN 0x000c
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_ARCH_QSD8X50) || defined (CONFIG_ARCH_MSM7X30)
|
||||
#if defined (CONFIG_ARCH_QSD8X50)
|
||||
#define MDDI_HOST_REV_RATE_DIV 0x0004
|
||||
#elif defined (CONFIG_ARCH_MSM7X30)
|
||||
#define MDDI_HOST_REV_RATE_DIV 0x0010
|
||||
#else
|
||||
#define MDDI_HOST_REV_RATE_DIV 0x0002
|
||||
#endif
|
||||
|
@ -21,10 +21,10 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/android_pmem.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/msm_hw3d.h>
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/msm_fb.h>
|
||||
@ -36,10 +36,16 @@
|
||||
|
||||
struct class *mdp_class;
|
||||
|
||||
#ifdef CONFIG_MSM_HDMI
|
||||
/* Used to report LCDC underflows */
|
||||
void reportUnderflow(void);
|
||||
#endif
|
||||
|
||||
#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
|
||||
static unsigned int mdp_irq_mask;
|
||||
static unsigned int mdp_dma_timer_enable = 0;
|
||||
struct clk *mdp_clk_to_disable_later = 0;
|
||||
static struct mdp_blit_req *timeout_req;
|
||||
#ifdef CONFIG_FB_MSM_OVERLAY
|
||||
@ -53,7 +59,19 @@ extern void mdp4_mddi_overlay(void *priv, uint32_t addr, uint32_t stride,
|
||||
uint32_t y);
|
||||
#include "mdp4.h"
|
||||
#endif
|
||||
DEFINE_MUTEX(mdp_mutex);
|
||||
|
||||
|
||||
static void mdp_do_standby_timer(unsigned long data)
|
||||
{
|
||||
struct mdp_info *mdp = (struct mdp_info *) data;
|
||||
if (!mdp_irq_mask) {
|
||||
clk_set_rate(mdp->ebi1_clk, 0);
|
||||
mdp->state |= MDP_STATE_STANDBY;
|
||||
} else {
|
||||
mod_timer(&mdp->standby_timer,
|
||||
jiffies + msecs_to_jiffies(200));
|
||||
}
|
||||
}
|
||||
|
||||
static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
{
|
||||
@ -69,7 +87,17 @@ static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
if (!mdp_irq_mask) {
|
||||
clk_enable(mdp->clk);
|
||||
enable_irq(mdp->irq);
|
||||
clk_set_rate(mdp->ebi1_clk, 128000000);
|
||||
if (mdp->state & MDP_STATE_STANDBY) {
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
clk_set_rate(mdp->ebi1_clk, 153000000);
|
||||
#else
|
||||
clk_set_rate(mdp->ebi1_clk, 128000000);
|
||||
#endif
|
||||
mdp->state &= ~MDP_STATE_STANDBY;
|
||||
} else {
|
||||
del_timer_sync(&mdp->standby_timer);
|
||||
barrier();
|
||||
}
|
||||
}
|
||||
|
||||
/* clear out any previous irqs for the requested mask*/
|
||||
@ -84,7 +112,7 @@ static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
|
||||
static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long flags=0;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, flags);
|
||||
@ -111,14 +139,16 @@ static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
disable_irq_nosync(mdp->irq);
|
||||
if (mdp->clk)
|
||||
clk_disable(mdp->clk);
|
||||
clk_set_rate(mdp->ebi1_clk, 0);
|
||||
if (!(mdp->state & MDP_STATE_STANDBY))
|
||||
mod_timer(&mdp->standby_timer,
|
||||
jiffies + msecs_to_jiffies(200));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, irq_flags);
|
||||
@ -130,7 +160,7 @@ int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
|
||||
static irqreturn_t mdp_isr(int irq, void *data)
|
||||
{
|
||||
uint32_t status;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
struct mdp_info *mdp = data;
|
||||
int i;
|
||||
|
||||
@ -139,13 +169,22 @@ static irqreturn_t mdp_isr(int irq, void *data)
|
||||
status = mdp_readl(mdp, MDP_INTR_STATUS);
|
||||
mdp_writel(mdp, status, MDP_INTR_CLEAR);
|
||||
|
||||
|
||||
#if defined(CONFIG_MACH_HTCLEO)
|
||||
status &= ~0x10000; // Cotulla
|
||||
#endif
|
||||
|
||||
// pr_info("%s: status=%08x (irq_mask=%08x)\n", __func__, status,
|
||||
// mdp_irq_mask);
|
||||
|
||||
if (mdp_dma_timer_enable) {
|
||||
del_timer_sync(&mdp->dma_timer);
|
||||
mdp_dma_timer_enable = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MSM_HDMI
|
||||
if (status & MDP_LCDC_UNDERFLOW)
|
||||
{
|
||||
pr_err("%s: LCDC Underflow\n", __func__);
|
||||
reportUnderflow();
|
||||
}
|
||||
#endif
|
||||
status &= ~0x10000; // Cotulla
|
||||
status &= mdp_irq_mask;
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
if (mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
|
||||
@ -168,9 +207,9 @@ static irqreturn_t mdp_isr(int irq, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
if (status & DL0_ROI_DONE)
|
||||
wake_up(&mdp_ppp_waitqueue);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP40
|
||||
mdp_ppp_handle_isr(mdp, status);
|
||||
#endif
|
||||
if (status)
|
||||
locked_disable_mdp_irq(mdp, status);
|
||||
|
||||
@ -178,10 +217,43 @@ static irqreturn_t mdp_isr(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mdp_do_dma_timer(unsigned long data)
|
||||
{
|
||||
uint32_t status;
|
||||
struct mdp_info *mdp = (struct mdp_info *) data;
|
||||
unsigned long irq_flags=0;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, irq_flags);
|
||||
|
||||
status = mdp_readl(mdp, MDP_INTR_STATUS);
|
||||
mdp_writel(mdp, mdp_irq_mask, MDP_INTR_CLEAR);
|
||||
|
||||
for (i = 0; i < MSM_MDP_NUM_INTERFACES; ++i) {
|
||||
struct mdp_out_interface *out_if = &mdp->out_if[i];
|
||||
if (mdp_irq_mask & out_if->dma_mask) {
|
||||
if (out_if->dma_cb) {
|
||||
out_if->dma_cb->func(out_if->dma_cb);
|
||||
out_if->dma_cb = NULL;
|
||||
}
|
||||
wake_up(&out_if->dma_waitqueue);
|
||||
}
|
||||
if (mdp_irq_mask & out_if->irq_mask) {
|
||||
out_if->irq_cb->func(out_if->irq_cb);
|
||||
out_if->irq_cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
locked_disable_mdp_irq(mdp, mdp_irq_mask);
|
||||
|
||||
spin_unlock_irqrestore(&mdp->lock, irq_flags);
|
||||
|
||||
}
|
||||
|
||||
static uint32_t mdp_check_mask(struct mdp_info *mdp, uint32_t mask)
|
||||
{
|
||||
uint32_t ret;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, irq_flags);
|
||||
ret = mdp_irq_mask & mask;
|
||||
@ -189,10 +261,29 @@ static uint32_t mdp_check_mask(struct mdp_info *mdp, uint32_t mask)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
|
||||
void mdp_dump_blit(struct mdp_blit_req *req)
|
||||
{
|
||||
pr_info("%s: src: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
|
||||
req->src.width, req->src.height, req->src.format,
|
||||
req->src.offset, req->src.memory_id);
|
||||
pr_info("%s: dst: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
|
||||
req->dst.width, req->dst.height, req->dst.format,
|
||||
req->dst.offset, req->dst.memory_id);
|
||||
pr_info("%s: src_rect: x=%d y=%d w=%d h=%d\n", __func__,
|
||||
req->src_rect.x, req->src_rect.y, req->src_rect.w,
|
||||
req->src_rect.h);
|
||||
pr_info("%s: dst_rect: x=%d y=%d w=%d h=%d\n", __func__,
|
||||
req->dst_rect.x, req->dst_rect.y, req->dst_rect.w,
|
||||
req->dst_rect.h);
|
||||
pr_info("%s: alpha=0x%08x\n", __func__, req->alpha);
|
||||
pr_info("%s: transp_max=0x%08x\n", __func__, req->transp_mask);
|
||||
pr_info("%s: flags=%08x\n", __func__, req->flags);
|
||||
}
|
||||
|
||||
int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
// pr_info("%s: WAITING for 0x%x\n", __func__, mask);
|
||||
wait_event_timeout(*wq, !mdp_check_mask(mdp, mask), HZ);
|
||||
@ -214,7 +305,7 @@ static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
|
||||
static void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
|
||||
{
|
||||
#define MDP_MAX_TIMEOUTS 20
|
||||
static int timeout_count;
|
||||
@ -247,54 +338,42 @@ void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static int mdp_ppp_wait(struct mdp_info *mdp)
|
||||
{
|
||||
return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
|
||||
}
|
||||
|
||||
*/
|
||||
#ifndef CONFIG_MSM_MDP40
|
||||
static void mdp_dmas_to_mddi(void *priv, uint32_t addr, uint32_t stride,
|
||||
uint32_t width, uint32_t height, uint32_t x, uint32_t y)
|
||||
{
|
||||
struct mdp_info *mdp = priv;
|
||||
uint32_t dma2_cfg;
|
||||
uint32_t video_packet_parameter;
|
||||
uint32_t video_packet_parameter = 0;
|
||||
uint16_t ld_param = 1;
|
||||
|
||||
dma2_cfg = DMA_PACK_TIGHT |
|
||||
DMA_PACK_ALIGN_LSB |
|
||||
DMA_OUT_SEL_AHB |
|
||||
DMA_IBUF_NONCONTIGUOUS;
|
||||
|
||||
if(machine_is_htcleo()) {
|
||||
dma2_cfg = DMA_PACK_ALIGN_MSB |
|
||||
DMA_PACK_PATTERN_RGB;
|
||||
dma2_cfg |= mdp->dma_format;
|
||||
|
||||
dma2_cfg |= mdp->format;
|
||||
#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
|
||||
if (mdp->dma_format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
|
||||
#else
|
||||
if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888)
|
||||
#endif
|
||||
dma2_cfg |= DMA_PACK_PATTERN_BGR;
|
||||
else
|
||||
dma2_cfg |= DMA_PACK_PATTERN_RGB;
|
||||
|
||||
dma2_cfg |= DMA_OUT_SEL_LCDC;
|
||||
dma2_cfg |= DMA_OUT_SEL_MDDI;
|
||||
|
||||
dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
|
||||
|
||||
} else {
|
||||
dma2_cfg = DMA_PACK_TIGHT |
|
||||
DMA_PACK_ALIGN_LSB |
|
||||
DMA_OUT_SEL_AHB |
|
||||
DMA_IBUF_NONCONTIGUOUS;
|
||||
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
|
||||
|
||||
dma2_cfg |= mdp->format;
|
||||
|
||||
#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
|
||||
if (mdp->format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
|
||||
#else
|
||||
if (mdp->format == DMA_IBUF_FORMAT_XRGB8888)
|
||||
#endif
|
||||
dma2_cfg |= DMA_PACK_PATTERN_BGR;
|
||||
else
|
||||
dma2_cfg |= DMA_PACK_PATTERN_RGB;
|
||||
|
||||
dma2_cfg |= DMA_OUT_SEL_MDDI;
|
||||
|
||||
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
|
||||
|
||||
dma2_cfg |= DMA_DITHER_EN;
|
||||
}
|
||||
dma2_cfg |= DMA_DITHER_EN;
|
||||
|
||||
if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565) {
|
||||
dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
|
||||
@ -341,12 +420,12 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
|
||||
DMA_IBUF_NONCONTIGUOUS;
|
||||
|
||||
#endif
|
||||
dma2_cfg |= mdp->format;
|
||||
dma2_cfg |= mdp->dma_format;
|
||||
|
||||
#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
|
||||
if (mdp->format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
|
||||
if (mdp->dma_format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
|
||||
#else
|
||||
if (mdp->format == DMA_IBUF_FORMAT_XRGB8888)
|
||||
if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888)
|
||||
#endif
|
||||
dma2_cfg |= DMA_PACK_PATTERN_BGR;
|
||||
else
|
||||
@ -417,6 +496,7 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
|
||||
mdp_writel(mdp, 0, MDP_DMA_P_START);
|
||||
#endif
|
||||
}
|
||||
#endif /* ifndef CONFIG_MSM_MDP40 */
|
||||
|
||||
void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
|
||||
uint32_t width, uint32_t height, uint32_t x, uint32_t y,
|
||||
@ -435,54 +515,21 @@ void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, flags);
|
||||
if (locked_enable_mdp_irq(mdp, out_if->dma_mask)) {
|
||||
/* something wrong in dma, workaround it */
|
||||
mdp_dma_timer_enable = 1;
|
||||
pr_err("%s: busy\n", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
out_if->dma_cb = callback;
|
||||
out_if->dma_start(out_if->priv, addr, stride, width, height, x, y);
|
||||
done:
|
||||
|
||||
if (mdp_dma_timer_enable)
|
||||
mod_timer(&mdp->dma_timer,
|
||||
jiffies + msecs_to_jiffies(17));
|
||||
|
||||
spin_unlock_irqrestore(&mdp->lock, flags);
|
||||
}
|
||||
|
||||
static int get_img(struct mdp_img *img, struct fb_info *info,
|
||||
unsigned long *start, unsigned long *len,
|
||||
struct file** filep)
|
||||
{
|
||||
int put_needed, ret = 0;
|
||||
struct file *file;
|
||||
unsigned long vstart;
|
||||
|
||||
if (!get_pmem_file(img->memory_id, start, &vstart, len, filep))
|
||||
return 0;
|
||||
else if (!get_msm_hw3d_file(img->memory_id, &img->offset, start, len,
|
||||
filep))
|
||||
return 0;
|
||||
|
||||
file = fget_light(img->memory_id, &put_needed);
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
|
||||
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
|
||||
*start = info->fix.smem_start;
|
||||
*len = info->fix.smem_len;
|
||||
ret = 0;
|
||||
} else
|
||||
ret = -1;
|
||||
fput_light(file, put_needed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void put_img(struct file *file)
|
||||
{
|
||||
if (file) {
|
||||
if (is_pmem_file(file))
|
||||
put_pmem_file(file);
|
||||
else if (is_msm_hw3d_file(file))
|
||||
put_msm_hw3d_file(file);
|
||||
}
|
||||
}
|
||||
|
||||
void mdp_configure_dma(struct mdp_device *mdp_dev)
|
||||
{
|
||||
@ -494,7 +541,7 @@ void mdp_configure_dma(struct mdp_device *mdp_dev)
|
||||
dma_cfg = mdp_readl(mdp, MDP_DMA_P_CONFIG);
|
||||
dma_cfg &= ~DMA_IBUF_FORMAT_MASK;
|
||||
dma_cfg &= ~DMA_PACK_PATTERN_MASK;
|
||||
dma_cfg |= (mdp->format | mdp->pack_pattern);
|
||||
dma_cfg |= (mdp->dma_format | mdp->dma_pack_pattern);
|
||||
mdp_writel(mdp, dma_cfg, MDP_DMA_P_CONFIG);
|
||||
mdp->dma_config_dirty = false;
|
||||
|
||||
@ -514,6 +561,13 @@ int mdp_check_output_format(struct mdp_device *mdp_dev, int bpp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mdp_set_panel_size(struct mdp_device *mdp_dev, int width, int height)
|
||||
{
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
mdp->mdp_dev.width = width;
|
||||
mdp->mdp_dev.height = height;
|
||||
}
|
||||
|
||||
int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
|
||||
{
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
@ -542,214 +596,24 @@ int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (format != mdp->format || pack_pattern != mdp->pack_pattern) {
|
||||
mdp->format = format;
|
||||
mdp->pack_pattern = pack_pattern;
|
||||
if (format != mdp->dma_format || pack_pattern != mdp->dma_pack_pattern) {
|
||||
mdp->dma_format = format;
|
||||
mdp->dma_pack_pattern = pack_pattern;
|
||||
mdp->dma_config_dirty = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_req(struct mdp_blit_req *req,
|
||||
unsigned long src_start, unsigned long src_len,
|
||||
unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
pr_err("flags: 0x%x\n", req->flags);
|
||||
pr_err("src_start: 0x%08lx\n", src_start);
|
||||
pr_err("src_len: 0x%08lx\n", src_len);
|
||||
pr_err("src.offset: 0x%x\n", req->src.offset);
|
||||
pr_err("src.format: 0x%x\n", req->src.format);
|
||||
pr_err("src.width: %d\n", req->src.width);
|
||||
pr_err("src.height: %d\n", req->src.height);
|
||||
pr_err("src_rect.x: %d\n", req->src_rect.x);
|
||||
pr_err("src_rect.y: %d\n", req->src_rect.y);
|
||||
pr_err("src_rect.w: %d\n", req->src_rect.w);
|
||||
pr_err("src_rect.h: %d\n", req->src_rect.h);
|
||||
|
||||
pr_err("dst_start: 0x%08lx\n", dst_start);
|
||||
pr_err("dst_len: 0x%08lx\n", dst_len);
|
||||
pr_err("dst.offset: 0x%x\n", req->dst.offset);
|
||||
pr_err("dst.format: 0x%x\n", req->dst.format);
|
||||
pr_err("dst.width: %d\n", req->dst.width);
|
||||
pr_err("dst.height: %d\n", req->dst.height);
|
||||
pr_err("dst_rect.x: %d\n", req->dst_rect.x);
|
||||
pr_err("dst_rect.y: %d\n", req->dst_rect.y);
|
||||
pr_err("dst_rect.w: %d\n", req->dst_rect.w);
|
||||
pr_err("dst_rect.h: %d\n", req->dst_rect.h);
|
||||
}
|
||||
|
||||
int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
int ret;
|
||||
enable_mdp_irq(mdp, DL0_ROI_DONE);
|
||||
ret = mdp_ppp_blit(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (unlikely(ret)) {
|
||||
disable_mdp_irq(mdp, DL0_ROI_DONE);
|
||||
return ret;
|
||||
}
|
||||
ret = mdp_ppp_wait(mdp);
|
||||
if (unlikely(ret)) {
|
||||
printk(KERN_ERR "%s: failed!\n", __func__);
|
||||
pr_err("original request:\n");
|
||||
dump_req(mdp->req, src_start, src_len, dst_start, dst_len);
|
||||
pr_err("dead request:\n");
|
||||
dump_req(req, src_start, src_len, dst_start, dst_len);
|
||||
BUG();
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
|
||||
struct mdp_blit_req *req)
|
||||
{
|
||||
int ret;
|
||||
unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
struct file *src_file = 0, *dst_file = 0;
|
||||
|
||||
#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP302)
|
||||
if (req->flags & MDP_ROT_90) {
|
||||
if (unlikely(((req->dst_rect.h == 1) &&
|
||||
((req->src_rect.w != 1) ||
|
||||
(req->dst_rect.w != req->src_rect.h))) ||
|
||||
((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
|
||||
(req->dst_rect.h != req->src_rect.w))))) {
|
||||
pr_err("mpd_ppp: error scaling when size is 1!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(((req->dst_rect.w == 1) &&
|
||||
((req->src_rect.w != 1) ||
|
||||
(req->dst_rect.h != req->src_rect.h))) ||
|
||||
((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
|
||||
(req->dst_rect.h != req->src_rect.h))))) {
|
||||
pr_err("mpd_ppp: error scaling when size is 1!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
|
||||
if (unlikely(req->src_rect.h == 0 ||
|
||||
req->src_rect.w == 0)) {
|
||||
printk(KERN_ERR "mdp_ppp: src img of zero size!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (unlikely(req->dst_rect.h == 0 ||
|
||||
req->dst_rect.w == 0))
|
||||
return -EINVAL;
|
||||
|
||||
/* do this first so that if this fails, the caller can always
|
||||
* safely call put_img */
|
||||
if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
|
||||
printk(KERN_ERR "mdp_ppp: could not retrieve src image from "
|
||||
"memory\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
|
||||
printk(KERN_ERR "mdp_ppp: could not retrieve dst image from "
|
||||
"memory\n");
|
||||
put_img(src_file);
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&mdp_mutex);
|
||||
|
||||
timeout_req = req;
|
||||
/* transp_masking unimplemented */
|
||||
req->transp_mask = MDP_TRANSP_NOP;
|
||||
mdp->req = req;
|
||||
#if !defined(CONFIG_MSM_MDP31) && !defined(CONFIG_MSM_MDP302)
|
||||
if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
|
||||
req->alpha != MDP_ALPHA_NOP ||
|
||||
HAS_ALPHA(req->src.format)) &&
|
||||
(req->flags & MDP_ROT_90 &&
|
||||
req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
|
||||
int i;
|
||||
unsigned int tiles = req->dst_rect.h / 16;
|
||||
unsigned int remainder = req->dst_rect.h % 16;
|
||||
req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
|
||||
req->dst_rect.h = 16;
|
||||
for (i = 0; i < tiles; i++) {
|
||||
ret = mdp_blit_and_wait(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (ret)
|
||||
goto end;
|
||||
req->dst_rect.y += 16;
|
||||
req->src_rect.x += req->src_rect.w;
|
||||
}
|
||||
if (!remainder)
|
||||
goto end;
|
||||
req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
|
||||
req->dst_rect.h = remainder;
|
||||
}
|
||||
#else
|
||||
/* Workarounds for MDP 3.1 hardware bugs */
|
||||
if (unlikely((mdp_get_bytes_per_pixel(req->dst.format) == 4) &&
|
||||
(req->dst_rect.w != 1) &&
|
||||
(((req->dst_rect.w % 8) == 6) ||
|
||||
((req->dst_rect.w % 32) == 3) ||
|
||||
((req->dst_rect.w % 32) == 1)))) {
|
||||
ret = mdp_ppp_blit_split_width(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
goto end;
|
||||
} else if (unlikely((req->dst_rect.w != 1) && (req->dst_rect.h != 1) &&
|
||||
((req->dst_rect.h % 32) == 3 ||
|
||||
(req->dst_rect.h % 32) == 1))) {
|
||||
ret = mdp_ppp_blit_split_height(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
ret = mdp_blit_and_wait(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
end:
|
||||
put_img(src_file);
|
||||
put_img(dst_file);
|
||||
mutex_unlock(&mdp_mutex);
|
||||
return ret;
|
||||
return mdp_ppp_blit(mdp, fb, req);
|
||||
}
|
||||
|
||||
int mdp_fb_mirror(struct mdp_device *mdp_dev,
|
||||
struct fb_info *src_fb, struct fb_info *dst_fb,
|
||||
struct mdp_blit_req *req)
|
||||
{
|
||||
int ret;
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
|
||||
if (!src_fb || !dst_fb)
|
||||
return -EINVAL;
|
||||
|
||||
enable_mdp_irq(mdp, DL0_ROI_DONE);
|
||||
ret = mdp_ppp_blit(mdp, req,
|
||||
-1, src_fb->fix.smem_start, src_fb->fix.smem_len,
|
||||
-1, dst_fb->fix.smem_start, dst_fb->fix.smem_len);
|
||||
if (ret)
|
||||
goto err_bad_blit;
|
||||
|
||||
ret = mdp_ppp_wait(mdp);
|
||||
if (ret) {
|
||||
pr_err("mdp_ppp_wait error\n");
|
||||
goto err_wait_failed;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_bad_blit:
|
||||
disable_mdp_irq(mdp, DL0_ROI_DONE);
|
||||
|
||||
err_wait_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
|
||||
{
|
||||
@ -765,7 +629,7 @@ int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
|
||||
mdp_dma_start_func_t dma_start)
|
||||
{
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
unsigned long flags;
|
||||
unsigned long flags=0;
|
||||
int ret = 0;
|
||||
|
||||
if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
|
||||
@ -798,7 +662,7 @@ int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
|
||||
uint32_t mask, struct msmfb_callback *cb)
|
||||
{
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
unsigned long flags;
|
||||
unsigned long flags=0;
|
||||
int ret = 0;
|
||||
|
||||
if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
|
||||
@ -841,94 +705,6 @@ int register_mdp_client(struct class_interface *cint)
|
||||
return class_interface_register(cint);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
void mdp_hw_init(struct mdp_info *mdp)
|
||||
{
|
||||
mdp_irq_mask = 0;
|
||||
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
|
||||
}
|
||||
#else
|
||||
#include "mdp_csc_table.h"
|
||||
|
||||
void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata)
|
||||
{
|
||||
mdp_writel(mdp, pdata->sync_config, MDP_SYNC_CONFIG_0);
|
||||
mdp_writel(mdp, 1, MDP_TEAR_CHECK_EN);
|
||||
mdp_writel(mdp, pdata->sync_thresh, MDP_SYNC_THRESH_0);
|
||||
mdp_writel(mdp, pdata->sync_start_pos, MDP_PRIM_START_POS);
|
||||
}
|
||||
void mdp_hw_init(struct mdp_info *mdp)
|
||||
{
|
||||
int n;
|
||||
int lcdc_enabled;
|
||||
|
||||
mdp_irq_mask = 0;
|
||||
|
||||
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
|
||||
|
||||
/* debug interface write access */
|
||||
mdp_writel(mdp, 1, 0x60);
|
||||
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP22
|
||||
lcdc_enabled = mdp_readl(mdp, MDP_LCDC_EN);
|
||||
/* disable lcdc */
|
||||
mdp_writel(mdp, 0, MDP_LCDC_EN);
|
||||
/* enable auto clock gating for all blocks by default */
|
||||
mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
|
||||
/* reset color/gamma correct parms */
|
||||
mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
|
||||
#endif
|
||||
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
|
||||
mdp_writel(mdp, 1, 0x60);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
|
||||
mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
|
||||
|
||||
/* clear up unused fg/main registers */
|
||||
/* comp.plane 2&3 ystride */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
|
||||
|
||||
/* unpacked pattern */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
|
||||
|
||||
/* comp.plane 2 & 3 */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
|
||||
|
||||
/* clear unused bg registers */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
|
||||
mdp_writel(mdp, csc_matrix_config_table[n].val,
|
||||
csc_matrix_config_table[n].reg);
|
||||
|
||||
mdp_ppp_init_scale(mdp);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP31
|
||||
mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
|
||||
#endif
|
||||
#ifndef CONFIG_MSM_MDP22
|
||||
if(lcdc_enabled)
|
||||
mdp_writel(mdp, 1, MDP_LCDC_EN);
|
||||
#endif
|
||||
}
|
||||
#endif //CONFIG_MSM_MDP40
|
||||
|
||||
int mdp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *resource;
|
||||
@ -974,9 +750,13 @@ int mdp_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
|
||||
mdp->mdp_dev.set_output_format = mdp_set_output_format;
|
||||
mdp->mdp_dev.set_panel_size = mdp_set_panel_size;
|
||||
mdp->mdp_dev.check_output_format = mdp_check_output_format;
|
||||
mdp->mdp_dev.configure_dma = mdp_configure_dma;
|
||||
|
||||
mdp->enable_irq = enable_mdp_irq;
|
||||
mdp->disable_irq = disable_mdp_irq;
|
||||
|
||||
if (pdata == NULL || pdata->overrides == 0)
|
||||
mdp->mdp_dev.overrides = 0;
|
||||
else if(pdata->overrides)
|
||||
@ -987,27 +767,27 @@ int mdp_probe(struct platform_device *pdev)
|
||||
else if(pdata->color_format)
|
||||
mdp->mdp_dev.color_format = pdata->color_format;
|
||||
|
||||
if (pdata == NULL || pdata->dma_channel == MDP_DMA_P) {
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
if (mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
|
||||
ret = mdp_out_if_register(&mdp->mdp_dev,
|
||||
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE
|
||||
| MDP_DMA_S_DONE, mdp4_mddi_overlay);
|
||||
} else {
|
||||
ret = mdp_out_if_register(&mdp->mdp_dev,
|
||||
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE,
|
||||
mdp4_mddi_overlay);
|
||||
}
|
||||
if (mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
|
||||
ret = mdp_out_if_register(&mdp->mdp_dev,
|
||||
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE
|
||||
| MDP_DMA_S_DONE, mdp4_mddi_overlay);
|
||||
} else {
|
||||
ret = mdp_out_if_register(&mdp->mdp_dev,
|
||||
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE,
|
||||
mdp4_mddi_overlay);
|
||||
}
|
||||
#else
|
||||
if (pdata == NULL || pdata->dma_channel == MDP_DMA_P) {
|
||||
ret = mdp_out_if_register(&mdp->mdp_dev,
|
||||
MSM_MDDI_PMDH_INTERFACE, mdp, MDP_DMA_P_DONE,
|
||||
mdp_dma_to_mddi);
|
||||
#endif
|
||||
} else if (pdata->dma_channel == MDP_DMA_S) {
|
||||
ret = mdp_out_if_register(&mdp->mdp_dev,
|
||||
MSM_MDDI_PMDH_INTERFACE, mdp, MDP_DMA_S_DONE,
|
||||
mdp_dmas_to_mddi);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret)
|
||||
goto error_mddi_pmdh_register;
|
||||
@ -1019,13 +799,12 @@ int mdp_probe(struct platform_device *pdev)
|
||||
goto error_get_mdp_clk;
|
||||
}
|
||||
|
||||
mdp->ebi1_clk = clk_get(NULL, "ebi1_clk");
|
||||
if (IS_ERR(mdp->ebi1_clk)) {
|
||||
pr_err("mdp: failed to get ebi1 clk\n");
|
||||
ret = PTR_ERR(mdp->ebi1_clk);
|
||||
goto error_get_ebi1_clk;
|
||||
}
|
||||
|
||||
mdp->ebi1_clk = clk_get(NULL, "ebi1_clk");
|
||||
if (IS_ERR(mdp->ebi1_clk)) {
|
||||
pr_err("mdp: failed to get ebi1 clk\n");
|
||||
ret = PTR_ERR(mdp->ebi1_clk);
|
||||
goto error_get_ebi1_clk;
|
||||
}
|
||||
|
||||
ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
|
||||
if (ret)
|
||||
@ -1034,6 +813,7 @@ int mdp_probe(struct platform_device *pdev)
|
||||
|
||||
clk_enable(mdp->clk);
|
||||
mdp_clk_to_disable_later = mdp->clk;
|
||||
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
//MDP_DISP_INTF_SEL
|
||||
if (mdp_readl(mdp, 0xc0000))
|
||||
@ -1045,7 +825,6 @@ int mdp_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
extern void mdp4_hw_init(struct mdp_info *mdp);
|
||||
mdp4_hw_init(mdp);
|
||||
#else
|
||||
mdp_hw_init(mdp);
|
||||
@ -1069,6 +848,10 @@ extern void mdp4_hw_init(struct mdp_info *mdp);
|
||||
if (ret)
|
||||
goto error_device_register;
|
||||
|
||||
setup_timer(&mdp->standby_timer, mdp_do_standby_timer, (unsigned long )mdp);
|
||||
setup_timer(&mdp->dma_timer, mdp_do_dma_timer, (unsigned long )mdp);
|
||||
|
||||
|
||||
pr_info("%s: initialized\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
@ -47,12 +47,61 @@ struct mdp_info {
|
||||
char * __iomem base;
|
||||
int irq;
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
struct clk *ebi1_clk;
|
||||
struct mdp_out_interface out_if[MSM_MDP_NUM_INTERFACES];
|
||||
int format;
|
||||
int pack_pattern;
|
||||
int dma_format;
|
||||
int dma_pack_pattern;
|
||||
bool dma_config_dirty;
|
||||
struct mdp_blit_req *req;
|
||||
uint32_t state;
|
||||
struct timer_list standby_timer;
|
||||
struct timer_list dma_timer;
|
||||
|
||||
int (*enable_irq)(struct mdp_info *mdp, uint32_t mask);
|
||||
int (*disable_irq)(struct mdp_info *mdp, uint32_t mask);
|
||||
};
|
||||
|
||||
struct mdp_lcdc_info {
|
||||
struct mdp_info *mdp;
|
||||
struct clk *mdp_clk;
|
||||
struct clk *mdp_pclk;
|
||||
struct clk *pclk;
|
||||
struct clk *pad_pclk;
|
||||
struct msm_panel_data fb_panel_data;
|
||||
struct platform_device fb_pdev;
|
||||
struct msm_lcdc_platform_data *pdata;
|
||||
uint32_t fb_start;
|
||||
|
||||
struct msmfb_callback frame_start_cb;
|
||||
wait_queue_head_t vsync_waitq;
|
||||
int got_vsync;
|
||||
unsigned color_format;
|
||||
struct {
|
||||
uint32_t clk_rate;
|
||||
uint32_t hsync_ctl;
|
||||
uint32_t vsync_period;
|
||||
uint32_t vsync_pulse_width;
|
||||
uint32_t display_hctl;
|
||||
uint32_t display_vstart;
|
||||
uint32_t display_vend;
|
||||
uint32_t hsync_skew;
|
||||
uint32_t polarity;
|
||||
} parms;
|
||||
atomic_t blank_count;
|
||||
struct mutex blank_lock;
|
||||
};
|
||||
|
||||
struct panel_icm_info {
|
||||
bool icm_mode;
|
||||
bool icm_doable;
|
||||
bool clock_enabled;
|
||||
int panel_update;
|
||||
bool icm_suspend;
|
||||
struct mutex icm_lock;
|
||||
struct mdp_lcdc_info *lcdc;
|
||||
spinlock_t lock;
|
||||
void (*force_leave)(void);
|
||||
};
|
||||
|
||||
extern int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
|
||||
@ -64,15 +113,21 @@ extern int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
|
||||
|
||||
struct mdp_blit_req;
|
||||
struct mdp_device;
|
||||
int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start,
|
||||
unsigned long src_len, struct file *dst_file,
|
||||
unsigned long dst_start, unsigned long dst_len);
|
||||
|
||||
void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
int mdp_hw_init(struct mdp_info *mdp);
|
||||
void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata);
|
||||
void mdp_dump_blit(struct mdp_blit_req *req);
|
||||
int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq);
|
||||
|
||||
#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
|
||||
#define mdp_readl(mdp, offset) readl(mdp->base + offset)
|
||||
#define panel_to_lcdc(p) container_of((p), struct mdp_lcdc_info, fb_panel_data)
|
||||
#define panel_to_dtv(p) container_of((p), struct mdp_dtv_info, fb_panel_data)
|
||||
|
||||
/* define mdp state for multi purpose */
|
||||
#define MDP_STATE_STANDBY (1 << 0)
|
||||
|
||||
|
||||
#ifdef CONFIG_MSM_MDP302
|
||||
#define MDP_SYNC_CONFIG_0 ( 0x00300)
|
||||
@ -142,6 +197,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
#define MDP_VSYNC_CTRL (0x0008c)
|
||||
#define MDP_MDDI_PARAM_WR_SEL (0x00090)
|
||||
#define MDP_MDDI_PARAM (0x00094)
|
||||
#define MDP_MDDI_DATA_XFR (0x00098)
|
||||
#define MDP_CGC_EN (0x00100)
|
||||
#define MDP_CMD_STATUS (0x10008)
|
||||
#define MDP_PROFILE_EN (0x10010)
|
||||
@ -292,6 +348,21 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
#define MDP_LCDC_HSYNC_SKEW (0xc0030)
|
||||
#define MDP_LCDC_TEST_CTL (0xc0034)
|
||||
#define MDP_LCDC_CTL_POLARITY (0xc0038)
|
||||
|
||||
#define MDP_DTV_EN (0xd0000)
|
||||
#define MDP_DTV_HSYNC_CTL (0xd0004)
|
||||
#define MDP_DTV_VSYNC_PERIOD (0xd0008)
|
||||
#define MDP_DTV_VSYNC_PULSE_WIDTH (0xd000c)
|
||||
#define MDP_DTV_DISPLAY_HCTL (0xd0018)
|
||||
#define MDP_DTV_DISPLAY_V_START (0xd001c)
|
||||
#define MDP_DTV_DISPLAY_V_END (0xd0020)
|
||||
#define MDP_DTV_ACTIVE_HCTL (0xd002c)
|
||||
#define MDP_DTV_ACTIVE_V_START (0xd0030)
|
||||
#define MDP_DTV_ACTIVE_V_END (0xd0038)
|
||||
#define MDP_DTV_BORDER_CLR (0xd0040)
|
||||
#define MDP_DTV_UNDERFLOW_CTL (0xd0044)
|
||||
#define MDP_DTV_HSYNC_SKEW (0xd0048)
|
||||
#define MDP_DTV_CTL_POLARITY (0xd0050)
|
||||
#else
|
||||
#define MDP_LCDC_EN (0xe0000)
|
||||
#define MDP_LCDC_HSYNC_CTL (0xe0004)
|
||||
@ -321,6 +392,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
#define TV_OUT_DMA3_DONE (1<<6)
|
||||
#define TV_ENC_UNDERRUN (1<<7)
|
||||
#define TV_OUT_FRAME_START (1<<13)
|
||||
#define MDP_HIST_DONE (1<<20)
|
||||
|
||||
#ifdef CONFIG_MSM_MDP22
|
||||
#define MDP_DMA_P_DONE (1 << 2)
|
||||
@ -800,6 +872,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
#define DMA_PACK_LOOSE 0
|
||||
#define DMA_PACK_ALIGN_LSB 0
|
||||
#define DMA_PACK_ALIGN_MSB (1<<7)
|
||||
#define DMA_PACK_ALIGN_MASK (1<<7)
|
||||
#define DMA_PACK_PATTERN_MASK (0x3f<<8)
|
||||
#define DMA_PACK_PATTERN_RGB \
|
||||
(MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
|
||||
@ -823,31 +896,14 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
#define DMA_IBUF_FORMAT_MASK (1 << 20)
|
||||
#define DMA_IBUF_NONCONTIGUOUS (1<<21)
|
||||
|
||||
#elif defined(CONFIG_MSM_MDP30)
|
||||
|
||||
#define DMA_OUT_SEL_AHB 0
|
||||
#define DMA_OUT_SEL_MDDI (1<<19)
|
||||
#define DMA_AHBM_LCD_SEL_PRIMARY 0
|
||||
#define DMA_AHBM_LCD_SEL_SECONDARY (0)
|
||||
#define DMA_IBUF_C3ALPHA_EN (0)
|
||||
#define DMA_DITHER_EN (1<<24)
|
||||
|
||||
#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
|
||||
#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (0)
|
||||
#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (0)
|
||||
|
||||
#define DMA_IBUF_FORMAT_MASK (1 << 20)
|
||||
#define DMA_IBUF_FORMAT_RGB565 (1<<25)
|
||||
#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 (1<<26)
|
||||
#define DMA_IBUF_NONCONTIGUOUS (0)
|
||||
|
||||
#else /* CONFIG_MSM_MDP31 | CONFIG_MSM_MDP302 */
|
||||
#else /* CONFIG_MSM_MDP31 || CONFIG_MSM_MDP40 */
|
||||
|
||||
#define DMA_OUT_SEL_AHB (0 << 19)
|
||||
#define DMA_OUT_SEL_MDDI (1 << 19)
|
||||
#define DMA_OUT_SEL_LCDC (2 << 19)
|
||||
#define DMA_OUT_SEL_LCDC_MDDI (3 << 19)
|
||||
#define DMA_DITHER_EN (1 << 24)
|
||||
#define DMA_DEFLKR_EN (1 << 24) /* dma_e */
|
||||
#define DMA_IBUF_FORMAT_RGB888 (0 << 25)
|
||||
#define DMA_IBUF_FORMAT_RGB565 (1 << 25)
|
||||
#define DMA_IBUF_FORMAT_XRGB8888 (2 << 25)
|
||||
@ -862,6 +918,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
|
||||
/* MDDI REGISTER ? */
|
||||
#define MDDI_VDO_PACKET_DESC_RGB565 0x5565
|
||||
#define MDDI_VDO_PACKET_DESC_RGB666 0x5666
|
||||
#define MDDI_VDO_PACKET_DESC_RGB888 0x5888
|
||||
#define MDDI_VDO_PACKET_PRIM 0xC3
|
||||
#define MDDI_VDO_PACKET_SECD 0xC0
|
||||
|
||||
|
242
drivers/video/msm/mdp_hw_legacy.c
Normal file
242
drivers/video/msm/mdp_hw_legacy.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
* Author: Dima Zavin <dima@android.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "mdp_hw.h"
|
||||
#include "mdp_ppp.h"
|
||||
#include "mdp_csc_table.h"
|
||||
|
||||
#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
|
||||
static unsigned int mdp_irq_mask;
|
||||
#if 0
|
||||
static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
|
||||
uint32_t width, uint32_t height, uint32_t x,
|
||||
uint32_t y)
|
||||
{
|
||||
struct mdp_info *mdp = priv;
|
||||
uint32_t dma2_cfg;
|
||||
uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
|
||||
|
||||
dma2_cfg = DMA_PACK_TIGHT |
|
||||
DMA_PACK_ALIGN_LSB |
|
||||
DMA_OUT_SEL_AHB |
|
||||
DMA_IBUF_NONCONTIGUOUS;
|
||||
|
||||
dma2_cfg |= mdp->dma_format;
|
||||
dma2_cfg |= mdp->dma_pack_pattern;
|
||||
|
||||
dma2_cfg |= DMA_OUT_SEL_MDDI;
|
||||
|
||||
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
|
||||
|
||||
dma2_cfg |= DMA_DITHER_EN;
|
||||
|
||||
/* 666 18BPP */
|
||||
dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
|
||||
|
||||
#ifdef CONFIG_MSM_MDP22
|
||||
/* setup size, address, and stride */
|
||||
mdp_writel(mdp, (height << 16) | (width),
|
||||
MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
|
||||
mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
|
||||
mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
|
||||
|
||||
/* set y & x offset and MDDI transaction parameters */
|
||||
mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
|
||||
mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
|
||||
if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565)
|
||||
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | MDDI_VDO_PACKET_PRIM,
|
||||
MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
|
||||
else
|
||||
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB666 << 16) | MDDI_VDO_PACKET_PRIM,
|
||||
MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
|
||||
mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
|
||||
|
||||
/* start DMA2 */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
|
||||
#else
|
||||
/* setup size, address, and stride */
|
||||
mdp_writel(mdp, (height << 16) | (width), MDP_DMA_P_SIZE);
|
||||
mdp_writel(mdp, addr, MDP_DMA_P_IBUF_ADDR);
|
||||
mdp_writel(mdp, stride, MDP_DMA_P_IBUF_Y_STRIDE);
|
||||
|
||||
/* set y & x offset and MDDI transaction parameters */
|
||||
mdp_writel(mdp, (y << 16) | (x), MDP_DMA_P_OUT_XY);
|
||||
mdp_writel(mdp, ld_param, MDP_MDDI_PARAM_WR_SEL);
|
||||
if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565)
|
||||
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | MDDI_VDO_PACKET_PRIM,
|
||||
MDP_MDDI_PARAM);
|
||||
else
|
||||
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB666 << 16) | MDDI_VDO_PACKET_PRIM,
|
||||
MDP_MDDI_PARAM);
|
||||
|
||||
mdp_writel(mdp, 0x1, MDP_MDDI_DATA_XFR);
|
||||
mdp_writel(mdp, dma2_cfg, MDP_DMA_P_CONFIG);
|
||||
mdp_writel(mdp, 0, MDP_DMA_P_START);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined CONFIG_MSM_MDP302
|
||||
void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata)
|
||||
{ mdp_writel(mdp, pdata->sync_config, MDP_SYNC_CONFIG_0);
|
||||
mdp_writel(mdp, 1, MDP_TEAR_CHECK_EN);
|
||||
mdp_writel(mdp, pdata->sync_thresh, MDP_SYNC_THRESH_0);
|
||||
mdp_writel(mdp, pdata->sync_start_pos, MDP_PRIM_START_POS);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
int mdp_hw_init(struct mdp_info *mdp)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = mdp_out_if_register(&mdp->mdp_dev, MSM_MDDI_PMDH_INTERFACE, mdp,
|
||||
MDP_DMA_P_DONE, mdp_dma_to_mddi);
|
||||
if (n)
|
||||
return n;
|
||||
|
||||
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
|
||||
|
||||
/* debug interface write access */
|
||||
mdp_writel(mdp, 1, 0x60);
|
||||
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP22
|
||||
/* disable lcdc */
|
||||
mdp_writel(mdp, 0, MDP_LCDC_EN);
|
||||
/* enable auto clock gating for all blocks by default */
|
||||
mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
|
||||
/* reset color/gamma correct parms */
|
||||
mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
|
||||
#endif
|
||||
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
|
||||
mdp_writel(mdp, 1, 0x60);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
|
||||
mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
|
||||
|
||||
/* clear up unused fg/main registers */
|
||||
/* comp.plane 2&3 ystride */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
|
||||
|
||||
/* unpacked pattern */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
|
||||
|
||||
/* comp.plane 2 & 3 */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
|
||||
|
||||
/* clear unused bg registers */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
|
||||
mdp_writel(mdp, csc_matrix_config_table[n].val,
|
||||
csc_matrix_config_table[n].reg);
|
||||
|
||||
mdp_ppp_init_scale(mdp);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP31
|
||||
mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mdp_hw_init(struct mdp_info *mdp)
|
||||
{
|
||||
int n;
|
||||
int lcdc_enabled;
|
||||
|
||||
mdp_irq_mask = 0;
|
||||
|
||||
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
|
||||
|
||||
/* debug interface write access */
|
||||
mdp_writel(mdp, 1, 0x60);
|
||||
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP22
|
||||
lcdc_enabled = mdp_readl(mdp, MDP_LCDC_EN);
|
||||
/* disable lcdc */
|
||||
mdp_writel(mdp, 0, MDP_LCDC_EN);
|
||||
/* enable auto clock gating for all blocks by default */
|
||||
mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
|
||||
/* reset color/gamma correct parms */
|
||||
mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
|
||||
#endif
|
||||
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
|
||||
mdp_writel(mdp, 1, 0x60);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
|
||||
mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
|
||||
|
||||
/* clear up unused fg/main registers */
|
||||
/* comp.plane 2&3 ystride */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
|
||||
|
||||
/* unpacked pattern */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
|
||||
|
||||
/* comp.plane 2 & 3 */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
|
||||
|
||||
/* clear unused bg registers */
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
|
||||
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
|
||||
mdp_writel(mdp, csc_matrix_config_table[n].val,
|
||||
csc_matrix_config_table[n].reg);
|
||||
|
||||
mdp_ppp_init_scale(mdp);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP31
|
||||
mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
|
||||
#endif
|
||||
#ifndef CONFIG_MSM_MDP22
|
||||
if (lcdc_enabled)
|
||||
mdp_writel(mdp, 1, MDP_LCDC_EN);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-types.h>
|
||||
@ -33,6 +34,9 @@
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
#include "mdp4.h"
|
||||
#endif
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
#include <linux/kthread.h>
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define D(fmt, args...) printk(KERN_INFO "Dispaly: " fmt, ##args)
|
||||
@ -43,32 +47,6 @@
|
||||
#if defined(CONFIG_ARCH_MSM7227)
|
||||
#define LCDC_MUX_CTL (MSM_TGPIO1_BASE + 0x278)
|
||||
#endif
|
||||
struct mdp_lcdc_info {
|
||||
struct mdp_info *mdp;
|
||||
struct clk *mdp_clk;
|
||||
struct clk *pclk;
|
||||
struct clk *pad_pclk;
|
||||
struct msm_panel_data fb_panel_data;
|
||||
struct platform_device fb_pdev;
|
||||
struct msm_lcdc_platform_data *pdata;
|
||||
uint32_t fb_start;
|
||||
|
||||
struct msmfb_callback frame_start_cb;
|
||||
wait_queue_head_t vsync_waitq;
|
||||
int got_vsync;
|
||||
unsigned color_format;
|
||||
struct {
|
||||
uint32_t clk_rate;
|
||||
uint32_t hsync_ctl;
|
||||
uint32_t vsync_period;
|
||||
uint32_t vsync_pulse_width;
|
||||
uint32_t display_hctl;
|
||||
uint32_t display_vstart;
|
||||
uint32_t display_vend;
|
||||
uint32_t hsync_skew;
|
||||
uint32_t polarity;
|
||||
} parms;
|
||||
};
|
||||
|
||||
static struct mdp_device *mdp_dev;
|
||||
|
||||
@ -76,7 +54,142 @@ static struct mdp_device *mdp_dev;
|
||||
static struct mdp4_overlay_pipe *lcdc_pipe;
|
||||
#endif
|
||||
|
||||
#define panel_to_lcdc(p) container_of((p), struct mdp_lcdc_info, fb_panel_data)
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
#if 0
|
||||
#define ICM_DBG(s...) printk("[icm]" s)
|
||||
#else
|
||||
#define ICM_DBG(s...) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* set the timeout to 200 milliseconds */
|
||||
#define PANEL_ENTER_IDLE_TIMEOUT HZ/5
|
||||
/* Afetr setting ICM=1, we need to keep sending the RGB signal more than 2-frame */
|
||||
#define PANEL_IDLE_STABLE_TIMEOUT 48
|
||||
|
||||
static struct task_struct *th_display;
|
||||
struct panel_icm_info *panel_icm;
|
||||
DECLARE_WAIT_QUEUE_HEAD(panel_update_wait_queue);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
static int icm_check_panel_update(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long irq_flags = 0;
|
||||
|
||||
spin_lock_irqsave(&panel_icm->lock, irq_flags);
|
||||
ret = panel_icm->panel_update;
|
||||
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int icm_thread(void *data)
|
||||
{
|
||||
struct mdp_lcdc_info *lcdc;
|
||||
struct msm_lcdc_panel_ops *panel_ops;
|
||||
int rc;
|
||||
unsigned long irq_flags = 0;
|
||||
|
||||
lcdc = data;
|
||||
panel_ops = lcdc->pdata->panel_ops;
|
||||
while (1) {
|
||||
rc = wait_event_timeout(panel_update_wait_queue, icm_check_panel_update() == 1, PANEL_ENTER_IDLE_TIMEOUT);
|
||||
ICM_DBG("ICM Thread:wake up rc=%d \n", rc);
|
||||
mutex_lock(&panel_icm->icm_lock);
|
||||
if (rc == 0 && icm_check_panel_update() != 1) {/* wait_timeout */
|
||||
ICM_DBG("EnterICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
|
||||
if (panel_icm->icm_mode == false && panel_icm->icm_doable == true) {
|
||||
|
||||
if (panel_ops->refresh_enable)
|
||||
panel_ops->refresh_enable(panel_ops);
|
||||
|
||||
panel_icm->icm_mode = true;
|
||||
msleep(PANEL_IDLE_STABLE_TIMEOUT);
|
||||
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
|
||||
clk_disable(lcdc->pad_pclk);
|
||||
clk_disable(lcdc->pclk);
|
||||
clk_disable(lcdc->mdp_clk);
|
||||
panel_icm->clock_enabled = false;
|
||||
pr_info("EnterICM: enter ICM MODE done!!!\n");
|
||||
}
|
||||
} else {/* get update event, no timeout */
|
||||
ICM_DBG("Leave ICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
|
||||
if (panel_icm->icm_mode == true && panel_icm->icm_doable == true) {
|
||||
clk_enable(lcdc->mdp_clk);
|
||||
clk_enable(lcdc->pclk);
|
||||
clk_enable(lcdc->pad_pclk);
|
||||
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
|
||||
panel_icm->clock_enabled = true;
|
||||
|
||||
if (panel_ops->refresh_disable)
|
||||
panel_ops->refresh_disable(panel_ops);
|
||||
|
||||
panel_icm->icm_mode = false;
|
||||
pr_info("LeaveICM: leave ICM MODE done !!!\n");
|
||||
}
|
||||
spin_lock_irqsave(&panel_icm->lock, irq_flags);
|
||||
panel_icm->panel_update = 0;
|
||||
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
|
||||
}
|
||||
mutex_unlock(&panel_icm->icm_lock);
|
||||
} /* end while */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void icm_force_leave(void)
|
||||
{
|
||||
struct msm_lcdc_panel_ops *panel_ops;
|
||||
unsigned long irq_flags = 0;
|
||||
|
||||
panel_ops = panel_icm->lcdc->pdata->panel_ops;
|
||||
|
||||
mutex_lock(&panel_icm->icm_lock);
|
||||
ICM_DBG("Force Leave ICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
|
||||
if (panel_icm->icm_mode == true) {
|
||||
clk_enable(panel_icm->lcdc->mdp_clk);
|
||||
clk_enable(panel_icm->lcdc->pclk);
|
||||
clk_enable(panel_icm->lcdc->pad_pclk);
|
||||
mdp_writel(panel_icm->lcdc->mdp, 1, MDP_LCDC_EN);
|
||||
panel_icm->clock_enabled = true;
|
||||
if (panel_ops->refresh_disable)
|
||||
panel_ops->refresh_disable(panel_ops);
|
||||
panel_icm->icm_mode = false;
|
||||
panel_icm->icm_doable = true;
|
||||
pr_info("ForceLeaveICM: leave ICM MODE done !!!\n");
|
||||
}
|
||||
spin_lock_irqsave(&panel_icm->lock, irq_flags);
|
||||
panel_icm->panel_update = 0;
|
||||
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
|
||||
mutex_unlock(&panel_icm->icm_lock);
|
||||
}
|
||||
|
||||
static int icm_init(struct mdp_lcdc_info *lcdc)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* init panel_icm_info */
|
||||
panel_icm = kzalloc(sizeof(struct panel_icm_info), GFP_KERNEL);
|
||||
if (!panel_icm)
|
||||
return -ENOMEM;
|
||||
panel_icm->icm_doable = 1;
|
||||
panel_icm->clock_enabled = true;
|
||||
panel_icm->lcdc = lcdc;
|
||||
panel_icm->force_leave = icm_force_leave;
|
||||
panel_icm->icm_suspend = false;
|
||||
mutex_init(&panel_icm->icm_lock);
|
||||
th_display = kthread_run(icm_thread, lcdc, "panel-enterIdle");
|
||||
if (IS_ERR(th_display)) {
|
||||
ret = PTR_ERR(th_display);
|
||||
pr_err("%s: panel_icm_thread create fail:%d!!!\n", __func__, ret);
|
||||
goto error_create_thread;
|
||||
}
|
||||
return ret;
|
||||
error_create_thread:
|
||||
kfree(panel_icm);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lcdc_unblank(struct msm_panel_data *fb_panel)
|
||||
{
|
||||
@ -85,7 +198,8 @@ static int lcdc_unblank(struct msm_panel_data *fb_panel)
|
||||
|
||||
pr_info("%s: ()\n", __func__);
|
||||
|
||||
panel_ops->unblank(panel_ops);
|
||||
if (panel_ops->unblank)
|
||||
panel_ops->unblank(panel_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -96,14 +210,28 @@ static int lcdc_blank(struct msm_panel_data *fb_panel)
|
||||
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
|
||||
|
||||
pr_info("%s: ()\n", __func__);
|
||||
panel_ops->blank(panel_ops);
|
||||
|
||||
if (panel_ops->blank)
|
||||
panel_ops->blank(panel_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcdc_shutdown(struct msm_panel_data *fb_panel)
|
||||
{
|
||||
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
|
||||
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
|
||||
|
||||
pr_info("%s: ()\n", __func__);
|
||||
|
||||
if (panel_ops->shutdown)
|
||||
panel_ops->shutdown(panel_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcdc_suspend(struct msm_panel_data *fb_panel)
|
||||
{
|
||||
int status;
|
||||
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
|
||||
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
|
||||
|
||||
@ -111,13 +239,39 @@ static int lcdc_suspend(struct msm_panel_data *fb_panel)
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7227)
|
||||
writel(0x0, LCDC_MUX_CTL);
|
||||
status = readl(LCDC_MUX_CTL);
|
||||
D("suspend_lcdc_mux_ctl = %x\n", status);
|
||||
D("suspend_lcdc_mux_ctl = %x\n", readl(LCDC_MUX_CTL));
|
||||
#endif
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
|
||||
mutex_lock(&panel_icm->icm_lock);
|
||||
panel_icm->icm_doable = false;
|
||||
pr_info("[ICM %s]: icm mode=%d, clock_enabled=%d\n", __func__, panel_icm->icm_mode, panel_icm->clock_enabled);
|
||||
if (panel_icm->icm_mode == true && panel_icm->clock_enabled == false) {
|
||||
if (panel_ops->refresh_disable)
|
||||
panel_ops->refresh_disable(panel_ops);
|
||||
panel_icm->icm_mode = false;
|
||||
} else {
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
|
||||
clk_disable(lcdc->pad_pclk);
|
||||
clk_disable(lcdc->pclk);
|
||||
clk_disable(lcdc->mdp_clk);
|
||||
}
|
||||
panel_icm->clock_enabled = false;
|
||||
mutex_unlock(&panel_icm->icm_lock);
|
||||
} else {
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
|
||||
clk_disable(lcdc->pad_pclk);
|
||||
clk_disable(lcdc->pclk);
|
||||
clk_disable(lcdc->mdp_clk);
|
||||
}
|
||||
#else
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
|
||||
clk_disable(lcdc->pad_pclk);
|
||||
clk_disable(lcdc->pclk);
|
||||
if (lcdc->mdp_pclk)
|
||||
clk_disable(lcdc->mdp_pclk);
|
||||
clk_disable(lcdc->mdp_clk);
|
||||
#endif
|
||||
if (panel_ops->uninit)
|
||||
panel_ops->uninit(panel_ops);
|
||||
|
||||
@ -126,7 +280,6 @@ static int lcdc_suspend(struct msm_panel_data *fb_panel)
|
||||
|
||||
static int lcdc_resume(struct msm_panel_data *fb_panel)
|
||||
{
|
||||
unsigned int status;
|
||||
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
|
||||
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
|
||||
|
||||
@ -136,17 +289,26 @@ static int lcdc_resume(struct msm_panel_data *fb_panel)
|
||||
if (panel_ops->init(panel_ops) < 0)
|
||||
printk(KERN_ERR "LCD init fail!\n");
|
||||
}
|
||||
|
||||
clk_enable(lcdc->mdp_clk);
|
||||
if (lcdc->mdp_pclk)
|
||||
clk_enable(lcdc->mdp_pclk);
|
||||
clk_enable(lcdc->pclk);
|
||||
clk_enable(lcdc->pad_pclk);
|
||||
#if defined(CONFIG_ARCH_MSM7227)
|
||||
writel(0x1, LCDC_MUX_CTL);
|
||||
status = readl(LCDC_MUX_CTL);
|
||||
D("resume_lcdc_mux_ctl = %x\n",status);
|
||||
D("resume_lcdc_mux_ctl = %x\n", readl(LCDC_MUX_CTL));
|
||||
#endif
|
||||
|
||||
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
|
||||
mutex_lock(&panel_icm->icm_lock);
|
||||
panel_icm->icm_doable = true;
|
||||
panel_icm->clock_enabled = true;
|
||||
panel_icm->icm_suspend = false;
|
||||
mutex_unlock(&panel_icm->icm_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -157,12 +319,13 @@ static int lcdc_hw_init(struct mdp_lcdc_info *lcdc)
|
||||
uint32_t dma_cfg;
|
||||
|
||||
clk_enable(lcdc->mdp_clk);
|
||||
if (lcdc->mdp_pclk)
|
||||
clk_enable(lcdc->mdp_pclk);
|
||||
clk_enable(lcdc->pclk);
|
||||
clk_enable(lcdc->pad_pclk);
|
||||
|
||||
clk_set_rate(lcdc->pclk, lcdc->parms.clk_rate);
|
||||
clk_set_rate(lcdc->pad_pclk, lcdc->parms.clk_rate);
|
||||
|
||||
/* write the lcdc params */
|
||||
mdp_writel(lcdc->mdp, lcdc->parms.hsync_ctl, MDP_LCDC_HSYNC_CTL);
|
||||
mdp_writel(lcdc->mdp, lcdc->parms.vsync_period, MDP_LCDC_VSYNC_PERIOD);
|
||||
@ -175,46 +338,45 @@ static int lcdc_hw_init(struct mdp_lcdc_info *lcdc)
|
||||
mdp_writel(lcdc->mdp, lcdc->parms.hsync_skew, MDP_LCDC_HSYNC_SKEW);
|
||||
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_BORDER_CLR);
|
||||
mdp_writel(lcdc->mdp, 0xff, MDP_LCDC_UNDERFLOW_CTL);
|
||||
mdp_writel(lcdc->mdp, 0x80000000 | 0xff, MDP_LCDC_UNDERFLOW_CTL);
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_HCTL);
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_START);
|
||||
mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_END);
|
||||
mdp_writel(lcdc->mdp, lcdc->parms.polarity, MDP_LCDC_CTL_POLARITY);
|
||||
|
||||
/* config the dma_p block that drives the lcdc data */
|
||||
mdp_writel(lcdc->mdp, lcdc->fb_start, MDP_DMA_P_IBUF_ADDR);
|
||||
mdp_writel(lcdc->mdp, (((fb_panel->fb_data->yres & 0x7ff) << 16) |
|
||||
(fb_panel->fb_data->xres & 0x7ff)),
|
||||
MDP_DMA_P_SIZE);
|
||||
|
||||
mdp_writel(lcdc->mdp, 0, MDP_DMA_P_OUT_XY);
|
||||
|
||||
dma_cfg = mdp_readl(lcdc->mdp, MDP_DMA_P_CONFIG);
|
||||
#if defined(CONFIG_MACH_HTCLEO)
|
||||
dma_cfg &= ~(DMA_PACK_PATTERN_MASK | DMA_PACK_ALIGN_MASK);
|
||||
dma_cfg |= (DMA_PACK_ALIGN_MSB |
|
||||
DMA_PACK_PATTERN_RGB |
|
||||
DMA_DITHER_EN);
|
||||
DMA_PACK_PATTERN_RGB |
|
||||
DMA_DITHER_EN);
|
||||
dma_cfg |= DMA_OUT_SEL_LCDC;
|
||||
dma_cfg |= DMA_IBUF_FORMAT_RGB565;
|
||||
//dma_cfg &= ~DMA_DITHER_EN; // solve color banding issue - marc1706
|
||||
//zeusk: dma_cfg |= DMA_IBUF_FORMAT_RGB565;
|
||||
dma_cfg &= ~DMA_DST_BITS_MASK;
|
||||
#else
|
||||
dma_cfg |= (DMA_PACK_ALIGN_LSB |
|
||||
DMA_PACK_PATTERN_RGB |
|
||||
DMA_DITHER_EN);
|
||||
dma_cfg |= DMA_OUT_SEL_LCDC;
|
||||
dma_cfg &= ~DMA_DST_BITS_MASK;
|
||||
#endif
|
||||
|
||||
if(lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB565)
|
||||
dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
|
||||
else if (lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB666)
|
||||
dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
|
||||
if (fb_panel->fb_data->output_format == MSM_MDP_OUT_IF_FMT_RGB666)
|
||||
dma_cfg |= DMA_DSTC0G_6BITS |
|
||||
DMA_DSTC1B_6BITS |
|
||||
DMA_DSTC2R_6BITS;
|
||||
else if (fb_panel->fb_data->output_format == MSM_MDP_OUT_IF_FMT_RGB888)
|
||||
dma_cfg |= DMA_DSTC0G_8BITS |
|
||||
DMA_DSTC1B_8BITS |
|
||||
DMA_DSTC2R_8BITS;
|
||||
else
|
||||
dma_cfg |= DMA_DSTC0G_6BITS |
|
||||
DMA_DSTC1B_5BITS |
|
||||
DMA_DSTC2R_5BITS;
|
||||
|
||||
mdp_writel(lcdc->mdp, dma_cfg, MDP_DMA_P_CONFIG);
|
||||
|
||||
/* enable the lcdc timing generation */
|
||||
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -301,35 +463,6 @@ static void lcdc_dma_start(void *priv, uint32_t addr, uint32_t stride,
|
||||
mdp_writel(lcdc->mdp, addr, MDP_DMA_P_IBUF_ADDR);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
static void lcdc_overlay_start(void *priv, uint32_t addr, uint32_t stride,
|
||||
uint32_t width, uint32_t height, uint32_t x,
|
||||
uint32_t y)
|
||||
{
|
||||
struct mdp_lcdc_info *lcdc = priv;
|
||||
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
|
||||
|
||||
struct mdp4_overlay_pipe *pipe;
|
||||
pipe = lcdc_pipe;
|
||||
pipe->srcp0_addr = addr;
|
||||
|
||||
if (mdp->dma_config_dirty)
|
||||
{
|
||||
if(mdp->format == DMA_IBUF_FORMAT_RGB565) {
|
||||
pipe->src_format = MDP_RGB_565;
|
||||
pipe->srcp0_ystride = pipe->src_width * 2;
|
||||
} else if(mdp->format == DMA_IBUF_FORMAT_XRGB8888) {
|
||||
pipe->src_format = MDP_RGBA_8888;
|
||||
pipe->srcp0_ystride = pipe->src_width * 4;
|
||||
}
|
||||
mdp4_overlay_format2pipe(pipe);
|
||||
mdp->dma_config_dirty = false;
|
||||
}
|
||||
mdp4_overlay_rgb_setup(pipe);
|
||||
mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
|
||||
|
||||
}
|
||||
#endif
|
||||
static void precompute_timing_parms(struct mdp_lcdc_info *lcdc)
|
||||
{
|
||||
struct msm_lcdc_timing *timing = lcdc->pdata->timing;
|
||||
@ -404,6 +537,10 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
|
||||
goto err_get_mdp_clk;
|
||||
}
|
||||
|
||||
lcdc->mdp_pclk = clk_get(mdp_dev->dev.parent, "mdp_pclk");
|
||||
if (IS_ERR(lcdc->mdp_pclk))
|
||||
lcdc->mdp_pclk = NULL;
|
||||
|
||||
lcdc->pclk = clk_get(mdp_dev->dev.parent, "lcdc_pclk_clk");
|
||||
if (IS_ERR(lcdc->pclk)) {
|
||||
pr_err("%s: failed to get lcdc_pclk\n", __func__);
|
||||
@ -443,7 +580,10 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
|
||||
if (lcdc_pipe == NULL) {
|
||||
ptype = mdp4_overlay_format2type(MDP_RGB_565);
|
||||
pipe = mdp4_overlay_pipe_alloc(ptype);
|
||||
if (!pipe)
|
||||
goto err_mdp4_overlay_pipe_alloc;
|
||||
pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
|
||||
pipe->pipe_used = 1;
|
||||
pipe->mixer_num = MDP4_MIXER0;
|
||||
pipe->src_format = MDP_RGB_565;
|
||||
mdp4_overlay_format2pipe(pipe);
|
||||
@ -463,15 +603,8 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
|
||||
pipe->srcp0_addr = (uint32_t) lcdc->fb_start;
|
||||
pipe->srcp0_ystride = pdata->fb_data->xres * 2;
|
||||
|
||||
mdp4_overlay_dmap_xy(pipe);
|
||||
mdp4_overlay_dmap_cfg(pipe, 1);
|
||||
|
||||
mdp4_overlay_rgb_setup(pipe);
|
||||
|
||||
mdp4_mixer_stage_up(pipe);
|
||||
|
||||
mdp4_overlayproc_cfg(pipe);
|
||||
mdp4_overlay_reg_flush(pipe, 1);
|
||||
#endif
|
||||
|
||||
lcdc->fb_panel_data.suspend = lcdc_suspend;
|
||||
@ -483,13 +616,12 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
|
||||
lcdc->fb_panel_data.unblank = lcdc_unblank;
|
||||
lcdc->fb_panel_data.fb_data = pdata->fb_data;
|
||||
lcdc->fb_panel_data.interface_type = MSM_LCDC_INTERFACE;
|
||||
|
||||
lcdc->fb_panel_data.shutdown = lcdc_shutdown;
|
||||
ret = lcdc_hw_init(lcdc);
|
||||
if (ret) {
|
||||
pr_err("%s: Cannot initialize the mdp_lcdc\n", __func__);
|
||||
goto err_hw_init;
|
||||
}
|
||||
|
||||
lcdc->fb_pdev.name = "msm_panel";
|
||||
lcdc->fb_pdev.id = pdata->fb_id;
|
||||
lcdc->fb_pdev.resource = pdata->fb_resource;
|
||||
@ -504,16 +636,30 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
pr_info("%s: initialized\n", __func__);
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
|
||||
ret = icm_init(lcdc);
|
||||
if (ret) {
|
||||
pr_err("%s: Cannot init dispaly selfrefresh \n", __func__);
|
||||
goto err_plat_dev_reg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err_plat_dev_reg:
|
||||
err_hw_init:
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
err_mdp4_overlay_pipe_alloc:
|
||||
#endif
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
clk_put(lcdc->pad_pclk);
|
||||
err_get_pad_pclk:
|
||||
clk_put(lcdc->pclk);
|
||||
err_get_pclk:
|
||||
if (lcdc->mdp_pclk)
|
||||
clk_put(lcdc->mdp_pclk);
|
||||
clk_put(lcdc->mdp_clk);
|
||||
err_get_mdp_clk:
|
||||
kfree(lcdc);
|
||||
|
@ -15,8 +15,12 @@
|
||||
#include <linux/fb.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/msm_hw3d.h>
|
||||
#include <linux/msm_mdp.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/android_pmem.h>
|
||||
#include <linux/wait.h>
|
||||
#include <mach/msm_fb.h>
|
||||
|
||||
#include "mdp_hw.h"
|
||||
@ -52,19 +56,19 @@ static uint32_t dst_img_cfg[] = {
|
||||
PPP_ARRAY1(CFG, DST)
|
||||
};
|
||||
|
||||
static uint32_t bytes_per_pixel[] = {
|
||||
static const uint32_t bytes_per_pixel[] = {
|
||||
[MDP_RGB_565] = 2,
|
||||
[MDP_RGB_888] = 3,
|
||||
[MDP_XRGB_8888] = 4,
|
||||
[MDP_Y_CBCR_H2V2] = 1,
|
||||
[MDP_ARGB_8888] = 4,
|
||||
[MDP_RGB_888] = 3,
|
||||
[MDP_Y_CRCB_H2V2] = 1,
|
||||
[MDP_YCRYCB_H2V1] = 2,
|
||||
[MDP_Y_CRCB_H2V1] = 1,
|
||||
[MDP_Y_CBCR_H2V1] = 1,
|
||||
[MDP_RGBA_8888] = 4,
|
||||
[MDP_BGRA_8888] = 4,
|
||||
[MDP_RGBX_8888] = 4,
|
||||
[MDP_Y_CBCR_H2V1] = 1,
|
||||
[MDP_Y_CBCR_H2V2] = 1,
|
||||
[MDP_Y_CRCB_H2V1] = 1,
|
||||
[MDP_Y_CRCB_H2V2] = 1,
|
||||
[MDP_YCRYCB_H2V1] = 2
|
||||
};
|
||||
|
||||
static uint32_t dst_op_chroma[] = {
|
||||
@ -79,6 +83,9 @@ static uint32_t bg_op_chroma[] = {
|
||||
PPP_ARRAY1(CHROMA_SAMP, BG)
|
||||
};
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
|
||||
DEFINE_MUTEX(mdp_mutex);
|
||||
|
||||
static uint32_t get_luma_offset(struct mdp_img *img,
|
||||
struct mdp_rect *rect, uint32_t bpp)
|
||||
{
|
||||
@ -268,7 +275,6 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
|
||||
req->alpha &= 0xff;
|
||||
/* ALPHA BLEND */
|
||||
if (HAS_ALPHA(req->src.format)) {
|
||||
#if !defined(CONFIG_MACH_HTCLEO)
|
||||
regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON;
|
||||
if (req->flags & MDP_BLEND_FG_PREMULT) {
|
||||
#ifdef CONFIG_MSM_MDP31
|
||||
@ -285,10 +291,6 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
|
||||
} else {
|
||||
regs->op |= PPP_OP_BLEND_SRCPIXEL_ALPHA;
|
||||
}
|
||||
#else
|
||||
regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON;
|
||||
regs->op |= PPP_OP_BLEND_SRCPIXEL_ALPHA;
|
||||
#endif
|
||||
} else if (req->alpha < MDP_ALPHA_NOP) {
|
||||
/* just blend by alpha */
|
||||
regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
|
||||
@ -309,7 +311,7 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
|
||||
set_blend_region(&req->dst, &req->dst_rect, regs);
|
||||
}
|
||||
|
||||
static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
static int blit_scale(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct ppp_regs *regs)
|
||||
{
|
||||
struct mdp_rect dst_rect;
|
||||
@ -330,7 +332,7 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
}
|
||||
|
||||
if (mdp_ppp_cfg_scale(mdp, regs, &req->src_rect, &dst_rect,
|
||||
req->src.format, req->dst.format)) {
|
||||
req->src.format, req->dst.format)) {
|
||||
DLOG("crap, bad scale\n");
|
||||
return -1;
|
||||
}
|
||||
@ -339,7 +341,7 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
static void blit_blur(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct ppp_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
@ -411,21 +413,23 @@ static void flush_imgs(struct mdp_blit_req *req, struct ppp_regs *regs,
|
||||
#ifdef CONFIG_ANDROID_PMEM
|
||||
uint32_t src0_len, src1_len, dst0_len, dst1_len;
|
||||
|
||||
/* flush src images to memory before dma to mdp */
|
||||
get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
|
||||
&src1_len);
|
||||
flush_pmem_file(src_file, req->src.offset, src0_len);
|
||||
if (IS_PSEUDOPLNR(req->src.format))
|
||||
flush_pmem_file(src_file, req->src.offset + src0_len,
|
||||
src1_len);
|
||||
if (!(req->flags & MDP_BLIT_NON_CACHED)) {
|
||||
/* flush src images to memory before dma to mdp */
|
||||
get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
|
||||
&src1_len);
|
||||
flush_pmem_file(src_file, req->src.offset, src0_len);
|
||||
if (IS_PSEUDOPLNR(req->src.format))
|
||||
flush_pmem_file(src_file, req->src.offset + src0_len,
|
||||
src1_len);
|
||||
|
||||
/* flush dst images */
|
||||
get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
|
||||
&dst1_len);
|
||||
flush_pmem_file(dst_file, req->dst.offset, dst0_len);
|
||||
if (IS_PSEUDOPLNR(req->dst.format))
|
||||
flush_pmem_file(dst_file, req->dst.offset + dst0_len,
|
||||
dst1_len);
|
||||
/* flush dst images */
|
||||
get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
|
||||
&dst1_len);
|
||||
flush_pmem_file(dst_file, req->dst.offset, dst0_len);
|
||||
if (IS_PSEUDOPLNR(req->dst.format))
|
||||
flush_pmem_file(dst_file, req->dst.offset + dst0_len,
|
||||
dst1_len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -439,6 +443,13 @@ static uint32_t get_chroma_base(struct mdp_img *img, uint32_t base,
|
||||
return addr;
|
||||
}
|
||||
|
||||
int mdp_get_bytes_per_pixel(int format)
|
||||
{
|
||||
if (format < 0 || format >= MDP_IMGTYPE_LIMIT)
|
||||
return -1;
|
||||
return bytes_per_pixel[format];
|
||||
}
|
||||
|
||||
#if PPP_DUMP_BLITS
|
||||
#define mdp_writel_dbg(mdp, val, reg) do { \
|
||||
pr_info("%s: writing 0x%08x=0x%08x\n", __func__, (reg), (val));\
|
||||
@ -501,19 +512,17 @@ static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
mdp_writel_dbg(mdp, regs->bg_img_sz, MDP_PPP_BG_IMAGE_SIZE);
|
||||
mdp_writel_dbg(mdp, regs->bg_alpha_sel,
|
||||
MDP_PPP_BLEND_BG_ALPHA_SEL);
|
||||
|
||||
#if defined(CONFIG_MACH_HTCLEO)
|
||||
#if 0 /* zeusk: defined(CONFIG_MACH_HTCLEO) */
|
||||
mdp_writel_dbg(mdp, 0, MDP_TFETCH_TEST_MODE);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
if( src_file != -1 && dst_file != -1 )
|
||||
flush_imgs(req, regs, src_file, dst_file);
|
||||
flush_imgs(req, regs, src_file, dst_file);
|
||||
mdp_writel_dbg(mdp, 0x1000, MDP_DISPLAY0_START);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mdp_dump_blit(struct mdp_blit_req *req)
|
||||
/*
|
||||
static void mdp_dump_blit(struct mdp_blit_req *req)
|
||||
{
|
||||
pr_info("%s: src: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
|
||||
req->src.width, req->src.height, req->src.format,
|
||||
@ -531,8 +540,8 @@ void mdp_dump_blit(struct mdp_blit_req *req)
|
||||
pr_info("%s: transp_max=0x%08x\n", __func__, req->transp_mask);
|
||||
pr_info("%s: flags=%08x\n", __func__, req->flags);
|
||||
}
|
||||
|
||||
int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
*/
|
||||
static int process_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
@ -644,13 +653,6 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdp_get_bytes_per_pixel(int format)
|
||||
{
|
||||
if (format < 0 || format >= MDP_IMGTYPE_LIMIT)
|
||||
return -1;
|
||||
return bytes_per_pixel[format];
|
||||
}
|
||||
|
||||
#define mdp_dump_register(mdp, reg) \
|
||||
printk(# reg ": %08x\n", mdp_readl((mdp), (reg)))
|
||||
|
||||
@ -668,234 +670,164 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp)
|
||||
mdp_dump_register(mdp, MDP_INTR_ENABLE);
|
||||
}
|
||||
|
||||
|
||||
/* Splits a blit into two horizontal stripes. Used to work around MDP bugs */
|
||||
int mdp_ppp_blit_split_height(struct mdp_info *mdp, const struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
static int mdp_ppp_wait(struct mdp_info *mdp)
|
||||
{
|
||||
int ret;
|
||||
struct mdp_blit_req splitreq;
|
||||
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
|
||||
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
|
||||
|
||||
splitreq = *req;
|
||||
/* break dest roi at height*/
|
||||
d_x_0 = d_x_1 = req->dst_rect.x;
|
||||
d_w_0 = d_w_1 = req->dst_rect.w;
|
||||
d_y_0 = req->dst_rect.y;
|
||||
if (req->dst_rect.h % 32 == 3)
|
||||
d_h_1 = (req->dst_rect.h - 3) / 2 - 1;
|
||||
else
|
||||
d_h_1 = (req->dst_rect.h - 1) / 2 - 1;
|
||||
d_h_0 = req->dst_rect.h - d_h_1;
|
||||
d_y_1 = d_y_0 + d_h_0;
|
||||
if (req->dst_rect.h == 3) {
|
||||
d_h_1 = 2;
|
||||
d_h_0 = 2;
|
||||
d_y_1 = d_y_0 + 1;
|
||||
}
|
||||
/* break source roi */
|
||||
if (splitreq.flags & MDP_ROT_90) {
|
||||
s_y_0 = s_y_1 = req->src_rect.y;
|
||||
s_h_0 = s_h_1 = req->src_rect.h;
|
||||
s_x_0 = req->src_rect.x;
|
||||
s_w_1 = (req->src_rect.w * d_h_1) / req->dst_rect.h;
|
||||
s_w_0 = req->src_rect.w - s_w_1;
|
||||
s_x_1 = s_x_0 + s_w_0;
|
||||
if (d_h_1 >= 8 * s_w_1) {
|
||||
s_w_1++;
|
||||
s_x_1--;
|
||||
}
|
||||
} else {
|
||||
s_x_0 = s_x_1 = req->src_rect.x;
|
||||
s_w_0 = s_w_1 = req->src_rect.w;
|
||||
s_y_0 = req->src_rect.y;
|
||||
s_h_1 = (req->src_rect.h * d_h_1) / req->dst_rect.h;
|
||||
s_h_0 = req->src_rect.h - s_h_1;
|
||||
s_y_1 = s_y_0 + s_h_0;
|
||||
if (d_h_1 >= 8 * s_h_1) {
|
||||
s_h_1++;
|
||||
s_y_1--;
|
||||
}
|
||||
}
|
||||
|
||||
/* blit first region */
|
||||
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_90) ||
|
||||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
}
|
||||
ret = mdp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
ret = mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* blit second region */
|
||||
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_90) ||
|
||||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
}
|
||||
ret = mdp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
mdp_ppp_dump_debug(mdp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Splits a blit into two vertical stripes. Used to work around MDP bugs */
|
||||
int mdp_ppp_blit_split_width(struct mdp_info *mdp, const struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
static int get_img(struct mdp_img *img, struct fb_info *info,
|
||||
unsigned long *start, unsigned long *len,
|
||||
struct file** filep)
|
||||
{
|
||||
int put_needed, ret = 0;
|
||||
struct file *file;
|
||||
unsigned long vstart;
|
||||
|
||||
if (img->memory_id & 0x40000000)
|
||||
{
|
||||
struct fb_info *fb = registered_fb[img->memory_id & 0x0000FFFF];
|
||||
if (fb)
|
||||
{
|
||||
*start = fb->fix.smem_start;
|
||||
*len = fb->fix.smem_len;
|
||||
}
|
||||
*filep = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!get_pmem_file(img->memory_id, start, &vstart, len, filep))
|
||||
return 0;
|
||||
else if (!get_msm_hw3d_file(img->memory_id, &img->offset, start, len,
|
||||
filep))
|
||||
return 0;
|
||||
|
||||
file = fget_light(img->memory_id, &put_needed);
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
|
||||
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
|
||||
*start = info->fix.smem_start;
|
||||
*len = info->fix.smem_len;
|
||||
ret = 0;
|
||||
} else
|
||||
ret = -1;
|
||||
fput_light(file, put_needed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
void put_img(struct file *p_src_file)
|
||||
{
|
||||
#ifdef CONFIG_ANDROID_PMEM
|
||||
if (p_src_file)
|
||||
put_pmem_file(p_src_file);
|
||||
#else
|
||||
if (is_msm_hw3d_file(p_src_file))
|
||||
put_msm_hw3d_file(p_src_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dump_req(struct mdp_blit_req *req,
|
||||
unsigned long src_start, unsigned long src_len,
|
||||
unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
pr_err("flags: 0x%x\n", req->flags);
|
||||
pr_err("src_start: 0x%08lx\n", src_start);
|
||||
pr_err("src_len: 0x%08lx\n", src_len);
|
||||
pr_err("src.offset: 0x%x\n", req->src.offset);
|
||||
pr_err("src.format: 0x%x\n", req->src.format);
|
||||
pr_err("src.width: %d\n", req->src.width);
|
||||
pr_err("src.height: %d\n", req->src.height);
|
||||
pr_err("src_rect.x: %d\n", req->src_rect.x);
|
||||
pr_err("src_rect.y: %d\n", req->src_rect.y);
|
||||
pr_err("src_rect.w: %d\n", req->src_rect.w);
|
||||
pr_err("src_rect.h: %d\n", req->src_rect.h);
|
||||
|
||||
pr_err("dst_start: 0x%08lx\n", dst_start);
|
||||
pr_err("dst_len: 0x%08lx\n", dst_len);
|
||||
pr_err("dst.offset: 0x%x\n", req->dst.offset);
|
||||
pr_err("dst.format: 0x%x\n", req->dst.format);
|
||||
pr_err("dst.width: %d\n", req->dst.width);
|
||||
pr_err("dst.height: %d\n", req->dst.height);
|
||||
pr_err("dst_rect.x: %d\n", req->dst_rect.x);
|
||||
pr_err("dst_rect.y: %d\n", req->dst_rect.y);
|
||||
pr_err("dst_rect.w: %d\n", req->dst_rect.w);
|
||||
pr_err("dst_rect.h: %d\n", req->dst_rect.h);
|
||||
}
|
||||
|
||||
int mdp_ppp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
int ret;
|
||||
struct mdp_blit_req splitreq;
|
||||
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
|
||||
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
|
||||
splitreq = *req;
|
||||
|
||||
/* break dest roi at width*/
|
||||
d_y_0 = d_y_1 = req->dst_rect.y;
|
||||
d_h_0 = d_h_1 = req->dst_rect.h;
|
||||
d_x_0 = req->dst_rect.x;
|
||||
if (req->dst_rect.w % 32 == 6)
|
||||
d_w_1 = req->dst_rect.w / 2 - 1;
|
||||
else if (req->dst_rect.w % 2 == 0)
|
||||
d_w_1 = req->dst_rect.w / 2;
|
||||
else if (req->dst_rect.w % 32 == 3)
|
||||
d_w_1 = (req->dst_rect.w - 3) / 2 - 1;
|
||||
else
|
||||
d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
|
||||
d_w_0 = req->dst_rect.w - d_w_1;
|
||||
d_x_1 = d_x_0 + d_w_0;
|
||||
if (req->dst_rect.w == 3) {
|
||||
d_w_1 = 2;
|
||||
d_w_0 = 2;
|
||||
d_x_1 = d_x_0 + 1;
|
||||
mdp->enable_irq(mdp, DL0_ROI_DONE);
|
||||
ret = process_blit(mdp, req, src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (unlikely(ret)) {
|
||||
mdp->disable_irq(mdp, DL0_ROI_DONE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* break src roi at height or width*/
|
||||
if (splitreq.flags & MDP_ROT_90) {
|
||||
s_x_0 = s_x_1 = req->src_rect.x;
|
||||
s_w_0 = s_w_1 = req->src_rect.w;
|
||||
s_y_0 = req->src_rect.y;
|
||||
s_h_1 = (req->src_rect.h * d_w_1) / req->dst_rect.w;
|
||||
s_h_0 = req->src_rect.h - s_h_1;
|
||||
s_y_1 = s_y_0 + s_h_0;
|
||||
if (d_w_1 >= 8 * s_h_1) {
|
||||
s_h_1++;
|
||||
s_y_1--;
|
||||
}
|
||||
} else {
|
||||
s_y_0 = s_y_1 = req->src_rect.y;
|
||||
s_h_0 = s_h_1 = req->src_rect.h;
|
||||
s_x_0 = req->src_rect.x;
|
||||
s_w_1 = (req->src_rect.w * d_w_1) / req->dst_rect.w;
|
||||
s_w_0 = req->src_rect.w - s_w_1;
|
||||
s_x_1 = s_x_0 + s_w_0;
|
||||
if (d_w_1 >= 8 * s_w_1) {
|
||||
s_w_1++;
|
||||
s_x_1--;
|
||||
}
|
||||
ret = mdp_ppp_wait(mdp);
|
||||
if (unlikely(ret)) {
|
||||
printk(KERN_ERR "%s: failed!\n", __func__);
|
||||
pr_err("original request:\n");
|
||||
dump_req(mdp->req, src_start, src_len, dst_start, dst_len);
|
||||
pr_err("dead request:\n");
|
||||
dump_req(req, src_start, src_len, dst_start, dst_len);
|
||||
BUG();
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* blit first region */
|
||||
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_270) ||
|
||||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
}
|
||||
int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
|
||||
struct mdp_blit_req *req)
|
||||
{
|
||||
int ret;
|
||||
unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
|
||||
struct file *src_file = 0, *dst_file = 0;
|
||||
|
||||
if (unlikely((splitreq.dst_rect.h != 1) &&
|
||||
((splitreq.dst_rect.h % 32 == 3) ||
|
||||
(splitreq.dst_rect.h % 32) == 1)))
|
||||
ret = mdp_ppp_blit_split_height(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
else
|
||||
ret = mdp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
ret = mdp_ppp_validate_blit(mdp, req);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* blit second region */
|
||||
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_270) ||
|
||||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
/* do this first so that if this fails, the caller can always
|
||||
* safely call put_img */
|
||||
if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
|
||||
printk(KERN_ERR "mdp_ppp: could not retrieve src image from "
|
||||
"memory\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely((splitreq.dst_rect.h != 1) &&
|
||||
((splitreq.dst_rect.h % 32 == 3) ||
|
||||
(splitreq.dst_rect.h % 32) == 1)))
|
||||
ret = mdp_ppp_blit_split_height(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
else
|
||||
ret = mdp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
|
||||
printk(KERN_ERR "mdp_ppp: could not retrieve dst image from "
|
||||
"memory\n");
|
||||
put_img(src_file);
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&mdp_mutex);
|
||||
|
||||
/* transp_masking unimplemented */
|
||||
req->transp_mask = MDP_TRANSP_NOP;
|
||||
mdp->req = req;
|
||||
|
||||
ret = mdp_ppp_do_blit(mdp, req, src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
|
||||
put_img(src_file);
|
||||
put_img(dst_file);
|
||||
mutex_unlock(&mdp_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask)
|
||||
{
|
||||
if (mask & DL0_ROI_DONE)
|
||||
wake_up(&mdp_ppp_waitqueue);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#define _VIDEO_MSM_MDP_PPP_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#define PPP_DUMP_BLITS 0
|
||||
|
||||
struct ppp_regs {
|
||||
uint32_t src0;
|
||||
@ -63,40 +62,57 @@ struct ppp_regs {
|
||||
struct mdp_info;
|
||||
struct mdp_rect;
|
||||
struct mdp_blit_req;
|
||||
struct fb_info;
|
||||
|
||||
void mdp_ppp_init_scale(const struct mdp_info *mdp);
|
||||
int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
|
||||
uint32_t src_format, uint32_t dst_format);
|
||||
int mdp_ppp_load_blur(const struct mdp_info *mdp);
|
||||
void mdp_dump_blit(struct mdp_blit_req *req);
|
||||
|
||||
|
||||
#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP302)
|
||||
int mdp_ppp_blit_split_width(struct mdp_info *mdp, const struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len);
|
||||
int mdp_ppp_blit_split_height(struct mdp_info *mdp, const struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len);
|
||||
|
||||
#if defined(CONFIG_MSM_MDP302)
|
||||
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
|
||||
#else
|
||||
static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req,
|
||||
struct ppp_regs *regs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB_MSM_MDP_PPP
|
||||
int mdp_get_bytes_per_pixel(int format);
|
||||
int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len);
|
||||
int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
|
||||
struct mdp_blit_req *req);
|
||||
void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask);
|
||||
int mdp_ppp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start,
|
||||
unsigned long src_len, struct file *dst_file,
|
||||
unsigned long dst_start, unsigned long dst_len);
|
||||
|
||||
/* these must be provided by h/w specific ppp files */
|
||||
void mdp_ppp_init_scale(struct mdp_info *mdp);
|
||||
int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
|
||||
uint32_t src_format, uint32_t dst_format);
|
||||
int mdp_ppp_load_blur(struct mdp_info *mdp);
|
||||
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
|
||||
int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req);
|
||||
int mdp_ppp_do_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start,
|
||||
unsigned long src_len, struct file *dst_file,
|
||||
unsigned long dst_start, unsigned long dst_len);
|
||||
|
||||
#else
|
||||
|
||||
static inline int mdp_get_bytes_per_pixel(int format) { return -1; }
|
||||
static inline int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
|
||||
struct mdp_blit_req *req) { return -EINVAL; }
|
||||
static inline void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask) {}
|
||||
static inline int mdp_ppp_blit_and_wait(struct mdp_info *mdp,
|
||||
struct mdp_blit_req *req, struct file *src_file,
|
||||
unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start,
|
||||
unsigned long dst_len) { return 0; }
|
||||
|
||||
static inline void mdp_ppp_init_scale(struct mdp_info *mdp) {}
|
||||
static inline int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
|
||||
uint32_t src_format, uint32_t dst_format) { return 0; }
|
||||
static inline int mdp_ppp_load_blur(struct mdp_info *mdp) { return 0; }
|
||||
static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs) { return 0; }
|
||||
static inline int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req) { return -EINVAL; }
|
||||
static inline int mdp_ppp_do_blit(struct mdp_info *mdp,
|
||||
struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start,
|
||||
unsigned long src_len, struct file *dst_file,
|
||||
unsigned long dst_start, unsigned long dst_len) { return 0; }
|
||||
|
||||
|
||||
#endif /* CONFIG_FB_MSM_MDP_PPP */
|
||||
|
||||
#endif /* _VIDEO_MSM_MDP_PPP_H_ */
|
||||
|
@ -1016,7 +1016,7 @@ static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
|
||||
uint32_t src_format, uint32_t dst_format)
|
||||
{
|
||||
@ -1070,7 +1070,7 @@ int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
}
|
||||
|
||||
|
||||
int mdp_ppp_load_blur(const struct mdp_info *mdp)
|
||||
int mdp_ppp_load_blur(struct mdp_info *mdp)
|
||||
{
|
||||
if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
|
||||
downscale_y_table == MDP_DOWNSCALE_BLUR)) {
|
||||
@ -1082,10 +1082,64 @@ int mdp_ppp_load_blur(const struct mdp_info *mdp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mdp_ppp_init_scale(const struct mdp_info *mdp)
|
||||
void mdp_ppp_init_scale(struct mdp_info *mdp)
|
||||
{
|
||||
downscale_x_table = MDP_DOWNSCALE_MAX;
|
||||
downscale_y_table = MDP_DOWNSCALE_MAX;
|
||||
|
||||
load_table(mdp, mdp_upscale_table, ARRAY_SIZE(mdp_upscale_table));
|
||||
}
|
||||
|
||||
int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req)
|
||||
{
|
||||
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
|
||||
if (unlikely(req->src_rect.h == 0 ||
|
||||
req->src_rect.w == 0)) {
|
||||
pr_info("mdp_ppp: src img of zero size!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (unlikely(req->dst_rect.h == 0 ||
|
||||
req->dst_rect.w == 0))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdp_ppp_do_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start,
|
||||
unsigned long src_len, struct file *dst_file,
|
||||
unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
|
||||
req->alpha != MDP_ALPHA_NOP ||
|
||||
HAS_ALPHA(req->src.format)) &&
|
||||
(req->flags & MDP_ROT_90 &&
|
||||
req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
|
||||
int i;
|
||||
unsigned int tiles = req->dst_rect.h / 16;
|
||||
unsigned int remainder = req->dst_rect.h % 16;
|
||||
req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
|
||||
req->dst_rect.h = 16;
|
||||
for (i = 0; i < tiles; i++) {
|
||||
ret = mdp_ppp_blit_and_wait(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (ret)
|
||||
goto end;
|
||||
req->dst_rect.y += 16;
|
||||
req->src_rect.x += req->src_rect.w;
|
||||
}
|
||||
if (!remainder)
|
||||
goto end;
|
||||
req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
|
||||
req->dst_rect.h = remainder;
|
||||
}
|
||||
|
||||
ret = mdp_ppp_blit_and_wait(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ static int scale_idx(int factor)
|
||||
return idx;
|
||||
}
|
||||
|
||||
int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
|
||||
uint32_t src_format, uint32_t dst_format)
|
||||
{
|
||||
@ -319,16 +319,319 @@ int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdp_ppp_load_blur(const struct mdp_info *mdp)
|
||||
int mdp_ppp_load_blur(struct mdp_info *mdp)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
void mdp_ppp_init_scale(const struct mdp_info *mdp)
|
||||
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mdp_ppp_init_scale(struct mdp_info *mdp)
|
||||
{
|
||||
int scale;
|
||||
for (scale = 0; scale < MDP_SCALE_MAX; ++scale)
|
||||
load_table(mdp, scale, 0);
|
||||
}
|
||||
|
||||
/* Splits a blit into two horizontal stripes. Used to work around MDP bugs */
|
||||
static int blit_split_height(struct mdp_info *mdp, const struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
int ret;
|
||||
struct mdp_blit_req splitreq;
|
||||
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
|
||||
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
|
||||
|
||||
splitreq = *req;
|
||||
/* break dest roi at height*/
|
||||
d_x_0 = d_x_1 = req->dst_rect.x;
|
||||
d_w_0 = d_w_1 = req->dst_rect.w;
|
||||
d_y_0 = req->dst_rect.y;
|
||||
if (req->dst_rect.h % 32 == 3)
|
||||
d_h_1 = (req->dst_rect.h - 3) / 2 - 1;
|
||||
else
|
||||
d_h_1 = (req->dst_rect.h - 1) / 2 - 1;
|
||||
d_h_0 = req->dst_rect.h - d_h_1;
|
||||
d_y_1 = d_y_0 + d_h_0;
|
||||
if (req->dst_rect.h == 3) {
|
||||
d_h_1 = 2;
|
||||
d_h_0 = 2;
|
||||
d_y_1 = d_y_0 + 1;
|
||||
}
|
||||
/* break source roi */
|
||||
if (splitreq.flags & MDP_ROT_90) {
|
||||
s_y_0 = s_y_1 = req->src_rect.y;
|
||||
s_h_0 = s_h_1 = req->src_rect.h;
|
||||
s_x_0 = req->src_rect.x;
|
||||
s_w_1 = (req->src_rect.w * d_h_1) / req->dst_rect.h;
|
||||
s_w_0 = req->src_rect.w - s_w_1;
|
||||
s_x_1 = s_x_0 + s_w_0;
|
||||
if (d_h_1 >= 8 * s_w_1) {
|
||||
s_w_1++;
|
||||
s_x_1--;
|
||||
}
|
||||
} else {
|
||||
s_x_0 = s_x_1 = req->src_rect.x;
|
||||
s_w_0 = s_w_1 = req->src_rect.w;
|
||||
s_y_0 = req->src_rect.y;
|
||||
s_h_1 = (req->src_rect.h * d_h_1) / req->dst_rect.h;
|
||||
s_h_0 = req->src_rect.h - s_h_1;
|
||||
s_y_1 = s_y_0 + s_h_0;
|
||||
if (d_h_1 >= 8 * s_h_1) {
|
||||
s_h_1++;
|
||||
s_y_1--;
|
||||
}
|
||||
}
|
||||
|
||||
/* blit first region */
|
||||
if (((splitreq.flags & 0x07) == MDP_ROT_90) ||
|
||||
((splitreq.flags & 0x07) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
}
|
||||
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* blit second region */
|
||||
if (((splitreq.flags & 0x07) == MDP_ROT_90) ||
|
||||
((splitreq.flags & 0x07) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
}
|
||||
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Splits a blit into two vertical stripes. Used to work around MDP bugs */
|
||||
static int blit_split_width(struct mdp_info *mdp, const struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start, unsigned long src_len,
|
||||
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
int ret;
|
||||
struct mdp_blit_req splitreq;
|
||||
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
|
||||
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
|
||||
splitreq = *req;
|
||||
|
||||
/* break dest roi at width*/
|
||||
d_y_0 = d_y_1 = req->dst_rect.y;
|
||||
d_h_0 = d_h_1 = req->dst_rect.h;
|
||||
d_x_0 = req->dst_rect.x;
|
||||
if (req->dst_rect.w % 32 == 6)
|
||||
d_w_1 = req->dst_rect.w / 2 - 1;
|
||||
else if (req->dst_rect.w % 2 == 0)
|
||||
d_w_1 = req->dst_rect.w / 2;
|
||||
else if (req->dst_rect.w % 32 == 3)
|
||||
d_w_1 = (req->dst_rect.w - 3) / 2 - 1;
|
||||
else
|
||||
d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
|
||||
d_w_0 = req->dst_rect.w - d_w_1;
|
||||
d_x_1 = d_x_0 + d_w_0;
|
||||
if (req->dst_rect.w == 3) {
|
||||
d_w_1 = 2;
|
||||
d_w_0 = 2;
|
||||
d_x_1 = d_x_0 + 1;
|
||||
}
|
||||
|
||||
/* break src roi at height or width*/
|
||||
if (splitreq.flags & MDP_ROT_90) {
|
||||
s_x_0 = s_x_1 = req->src_rect.x;
|
||||
s_w_0 = s_w_1 = req->src_rect.w;
|
||||
s_y_0 = req->src_rect.y;
|
||||
s_h_1 = (req->src_rect.h * d_w_1) / req->dst_rect.w;
|
||||
s_h_0 = req->src_rect.h - s_h_1;
|
||||
s_y_1 = s_y_0 + s_h_0;
|
||||
if (d_w_1 >= 8 * s_h_1) {
|
||||
s_h_1++;
|
||||
s_y_1--;
|
||||
}
|
||||
} else {
|
||||
s_y_0 = s_y_1 = req->src_rect.y;
|
||||
s_h_0 = s_h_1 = req->src_rect.h;
|
||||
s_x_0 = req->src_rect.x;
|
||||
s_w_1 = (req->src_rect.w * d_w_1) / req->dst_rect.w;
|
||||
s_w_0 = req->src_rect.w - s_w_1;
|
||||
s_x_1 = s_x_0 + s_w_0;
|
||||
if (d_w_1 >= 8 * s_w_1) {
|
||||
s_w_1++;
|
||||
s_x_1--;
|
||||
}
|
||||
}
|
||||
|
||||
/* blit first region */
|
||||
if (((splitreq.flags & 0x07) == MDP_ROT_270) ||
|
||||
((splitreq.flags & 0x07) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_0;
|
||||
splitreq.src_rect.y = s_y_0;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_0;
|
||||
splitreq.src_rect.w = s_w_0;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
}
|
||||
|
||||
if (unlikely((splitreq.dst_rect.h != 1) &&
|
||||
((splitreq.dst_rect.h % 32 == 3) ||
|
||||
(splitreq.dst_rect.h % 32) == 1)))
|
||||
ret = blit_split_height(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
else
|
||||
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* blit second region */
|
||||
if (((splitreq.flags & 0x07) == MDP_ROT_270) ||
|
||||
((splitreq.flags & 0x07) == 0x0)) {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_1;
|
||||
splitreq.dst_rect.y = d_y_1;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_1;
|
||||
splitreq.dst_rect.w = d_w_1;
|
||||
} else {
|
||||
splitreq.src_rect.h = s_h_1;
|
||||
splitreq.src_rect.y = s_y_1;
|
||||
splitreq.dst_rect.h = d_h_0;
|
||||
splitreq.dst_rect.y = d_y_0;
|
||||
splitreq.src_rect.x = s_x_1;
|
||||
splitreq.src_rect.w = s_w_1;
|
||||
splitreq.dst_rect.x = d_x_0;
|
||||
splitreq.dst_rect.w = d_w_0;
|
||||
}
|
||||
|
||||
if (unlikely((splitreq.dst_rect.h != 1) &&
|
||||
((splitreq.dst_rect.h % 32 == 3) ||
|
||||
(splitreq.dst_rect.h % 32) == 1)))
|
||||
ret = blit_split_height(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
else
|
||||
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req)
|
||||
{
|
||||
if (req->flags & MDP_ROT_90) {
|
||||
if (unlikely(((req->dst_rect.h == 1) &&
|
||||
((req->src_rect.w != 1) ||
|
||||
(req->dst_rect.w != req->src_rect.h))) ||
|
||||
((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
|
||||
(req->dst_rect.h != req->src_rect.w))))) {
|
||||
pr_err("mpd_ppp: error scaling when size is 1!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(((req->dst_rect.w == 1) &&
|
||||
((req->src_rect.w != 1) ||
|
||||
(req->dst_rect.h != req->src_rect.h))) ||
|
||||
((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
|
||||
(req->dst_rect.h != req->src_rect.h))))) {
|
||||
pr_err("mpd_ppp: error scaling when size is 1!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
|
||||
if (unlikely(req->src_rect.h == 0 ||
|
||||
req->src_rect.w == 0)) {
|
||||
pr_info("mdp_ppp: src img of zero size!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (unlikely(req->dst_rect.h == 0 ||
|
||||
req->dst_rect.w == 0))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdp_ppp_do_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
|
||||
struct file *src_file, unsigned long src_start,
|
||||
unsigned long src_len, struct file *dst_file,
|
||||
unsigned long dst_start, unsigned long dst_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Workarounds for MDP 3.1 hardware bugs */
|
||||
if (unlikely((mdp_get_bytes_per_pixel(req->dst.format) == 4) &&
|
||||
(req->dst_rect.w != 1) &&
|
||||
(((req->dst_rect.w % 8) == 6) ||
|
||||
((req->dst_rect.w % 32) == 3) ||
|
||||
((req->dst_rect.w % 32) == 1)))) {
|
||||
ret = blit_split_width(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
goto end;
|
||||
} else if (unlikely((req->dst_rect.w != 1) && (req->dst_rect.h != 1) &&
|
||||
((req->dst_rect.h % 32) == 3 ||
|
||||
(req->dst_rect.h % 32) == 1))) {
|
||||
ret = blit_split_height(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = mdp_ppp_blit_and_wait(mdp, req,
|
||||
src_file, src_start, src_len,
|
||||
dst_file, dst_start, dst_len);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,11 +33,17 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/android_pmem.h>
|
||||
#include "mdp_hw.h"
|
||||
|
||||
extern void start_drawing_late_resume(struct early_suspend *h);
|
||||
static void msmfb_resume_handler(struct early_suspend *h);
|
||||
static void msmfb_resume(struct work_struct *work);
|
||||
|
||||
#ifdef CONFIG_MSM_HDMI
|
||||
void hdmi_DoBlit(int offset);
|
||||
int hdmi_usePanelSync(void);
|
||||
#endif
|
||||
|
||||
#define MSMFB_DEBUG 1
|
||||
#ifdef CONFIG_FB_MSM_LOGO
|
||||
#define INIT_IMAGE_FILE "/logo.rle"
|
||||
@ -59,6 +65,11 @@ extern int load_565rle_image(char *filename);
|
||||
#define BLIT_TIME 0x4
|
||||
#define SHOW_UPDATES 0x8
|
||||
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
extern struct panel_icm_info *panel_icm;
|
||||
extern wait_queue_head_t panel_update_wait_queue;
|
||||
#endif
|
||||
|
||||
#define DLOG(mask, fmt, args...) \
|
||||
do { \
|
||||
if ((msmfb_debug_mask | SUSPEND_RESUME) & mask) \
|
||||
@ -72,6 +83,7 @@ module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
|
||||
S_IRUGO | S_IWUSR | S_IWGRP);
|
||||
|
||||
struct mdp_device *mdp;
|
||||
static atomic_t mdpclk_on = ATOMIC_INIT(1);
|
||||
|
||||
struct msmfb_info {
|
||||
struct fb_info *fb;
|
||||
@ -91,9 +103,13 @@ struct msmfb_info {
|
||||
int ebottom; /* exclusive */
|
||||
} update_info;
|
||||
char *black;
|
||||
|
||||
#ifdef CONFIG_HTC_ONMODE_CHARGING
|
||||
struct early_suspend onchg_earlier_suspend;
|
||||
struct early_suspend onchg_suspend;
|
||||
#endif
|
||||
struct early_suspend earlier_suspend;
|
||||
struct early_suspend early_suspend;
|
||||
|
||||
struct wake_lock idle_lock;
|
||||
spinlock_t update_lock;
|
||||
struct mutex panel_init_lock;
|
||||
@ -166,7 +182,7 @@ static int msmfb_release(struct fb_info *info, int user)
|
||||
/* Called from dma interrupt handler, must not sleep */
|
||||
static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
|
||||
dma_callback);
|
||||
#if PRINT_FPS
|
||||
@ -178,6 +194,7 @@ static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
|
||||
|
||||
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
|
||||
msmfb->frame_done = msmfb->frame_requested;
|
||||
|
||||
if (msmfb->sleeping == UPDATING &&
|
||||
msmfb->frame_done == msmfb->update_frame) {
|
||||
DLOG(SUSPEND_RESUME, "full update completed\n");
|
||||
@ -203,7 +220,7 @@ static int msmfb_start_dma(struct msmfb_info *msmfb)
|
||||
{
|
||||
uint32_t x, y, w, h;
|
||||
unsigned addr;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
uint32_t yoffset;
|
||||
s64 time_since_request;
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
@ -230,11 +247,13 @@ static int msmfb_start_dma(struct msmfb_info *msmfb)
|
||||
y = msmfb->update_info.top;
|
||||
w = msmfb->update_info.eright - x;
|
||||
h = msmfb->update_info.ebottom - y;
|
||||
|
||||
#if 0 /* zeusk: */
|
||||
;;;;;;ASD
|
||||
#if defined(CONFIG_FRAMEBUFFER_CONSOLE)
|
||||
x = 0; y = 0; w = msmfb->xres; h = msmfb->yres;
|
||||
#endif
|
||||
|
||||
ASD;;;;;;
|
||||
#endif
|
||||
yoffset = msmfb->yoffset;
|
||||
msmfb->update_info.left = msmfb->xres + 1;
|
||||
msmfb->update_info.top = msmfb->yres + 1;
|
||||
@ -287,7 +306,10 @@ static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
|
||||
{
|
||||
struct msmfb_info *msmfb = info->par;
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
unsigned long irq_flags;
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
struct mdp_lcdc_info *lcdc = panel_to_lcdc(panel);
|
||||
#endif
|
||||
unsigned long irq_flags=0;
|
||||
int sleeping;
|
||||
int retry = 1;
|
||||
#if PRINT_FPS
|
||||
@ -300,16 +322,21 @@ static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
|
||||
DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
|
||||
left, top, eright, ebottom, yoffset, pan_display);
|
||||
|
||||
#if !defined(CONFIG_MACH_HTCLEO)
|
||||
// For some reason we need to remove it here, state is 1, we have to look later to this problem
|
||||
if (msmfb->sleeping != AWAKE)
|
||||
DLOG(SUSPEND_RESUME, "pan_update in state(%d)\n", msmfb->sleeping);
|
||||
#ifdef CONFIG_PANEL_SELF_REFRESH
|
||||
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
|
||||
spin_lock_irqsave(&panel_icm->lock, irq_flags);
|
||||
panel_icm->panel_update = 1;
|
||||
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
|
||||
wake_up(&panel_update_wait_queue);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR))
|
||||
/* Jay, 8/1/09' */
|
||||
msmfb_set_var(msmfb->fb->screen_base, yoffset);
|
||||
#endif
|
||||
if (msmfb->sleeping != AWAKE)
|
||||
DLOG(SUSPEND_RESUME, "pan_update in state(%d)\n", msmfb->sleeping);
|
||||
|
||||
restart:
|
||||
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
|
||||
@ -401,19 +428,35 @@ restart:
|
||||
msmfb->yoffset);
|
||||
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
|
||||
|
||||
/* if the panel is all the way on wait for vsync, otherwise sleep
|
||||
* for 16 ms (long enough for the dma to panel) and then begin dma */
|
||||
msmfb->vsync_request_time = ktime_get();
|
||||
if (panel->request_vsync && (sleeping == AWAKE)) {
|
||||
wake_lock_timeout(&msmfb->idle_lock, HZ/4);
|
||||
panel->request_vsync(panel, &msmfb->vsync_callback);
|
||||
} else {
|
||||
if (!hrtimer_active(&msmfb->fake_vsync)) {
|
||||
hrtimer_start(&msmfb->fake_vsync,
|
||||
ktime_set(0, NSEC_PER_SEC/60),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_MSM_HDMI
|
||||
if (!hdmi_usePanelSync())
|
||||
{
|
||||
msmfb->vsync_request_time = ktime_get();
|
||||
msmfb_start_dma(msmfb);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
/* if the panel is all the way on wait for vsync, otherwise sleep
|
||||
* for 16 ms (long enough for the dma to panel) and then begin dma */
|
||||
msmfb->vsync_request_time = ktime_get();
|
||||
if (panel->request_vsync && (sleeping == AWAKE)) {
|
||||
wake_lock_timeout(&msmfb->idle_lock, HZ/4);
|
||||
panel->request_vsync(panel, &msmfb->vsync_callback);
|
||||
} else {
|
||||
if (!hrtimer_active(&msmfb->fake_vsync)) {
|
||||
hrtimer_start(&msmfb->fake_vsync,
|
||||
ktime_set(0, NSEC_PER_SEC/60),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_MSM_HDMI
|
||||
}
|
||||
|
||||
/* We did the DMA, now blit the data to the other display */
|
||||
hdmi_DoBlit(msmfb->xres * msmfb->yoffset * BYTES_PER_PIXEL(msmfb));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
|
||||
@ -427,7 +470,7 @@ static void power_on_panel(struct work_struct *work)
|
||||
struct msmfb_info *msmfb =
|
||||
container_of(work, struct msmfb_info, resume_work);
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
mutex_lock(&msmfb->panel_init_lock);
|
||||
DLOG(SUSPEND_RESUME, "turning on panel\n");
|
||||
if (msmfb->sleeping == UPDATING) {
|
||||
@ -447,34 +490,33 @@ error:
|
||||
mutex_unlock(&msmfb->panel_init_lock);
|
||||
}
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(display_chain_head);
|
||||
int register_display_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&display_chain_head, nb);
|
||||
}
|
||||
static int display_notifier_callback(struct notifier_block *nfb,
|
||||
unsigned long action,
|
||||
void *ignored)
|
||||
{
|
||||
struct msmfb_info *msm_fb = (struct msmfb_info *)ignored;
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(display_chain_head);
|
||||
int register_display_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&display_chain_head, nb);
|
||||
}
|
||||
static int display_notifier_callback(struct notifier_block *nfb,
|
||||
unsigned long action,
|
||||
void *ignored)
|
||||
{
|
||||
//struct msmfb_info *msm_fb = (struct msmfb_info *)ignored;
|
||||
|
||||
switch (action) {
|
||||
case NOTIFY_MSM_FB:
|
||||
printk(KERN_DEBUG "NOTIFY_MSM_FB\n");
|
||||
msmfb_resume(&msm_fb->early_suspend);
|
||||
break;
|
||||
printk(KERN_DEBUG "NOTIFY_MSM_FB\n");
|
||||
//msmfb_resume(&msm_fb->early_suspend);
|
||||
break;
|
||||
case NOTIFY_POWER:
|
||||
/* nothing to do */
|
||||
break;
|
||||
/* nothing to do */
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: unknown action in 0x%lx\n",
|
||||
__func__, action);
|
||||
return NOTIFY_BAD;
|
||||
printk(KERN_ERR "%s: unknown action in 0x%lx\n",
|
||||
__func__, action);
|
||||
return NOTIFY_BAD;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
/* turn off the panel */
|
||||
static void msmfb_earlier_suspend(struct early_suspend *h)
|
||||
@ -482,7 +524,7 @@ static void msmfb_earlier_suspend(struct early_suspend *h)
|
||||
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
|
||||
earlier_suspend);
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
mutex_lock(&msmfb->panel_init_lock);
|
||||
msmfb->sleeping = SLEEPING;
|
||||
@ -513,6 +555,8 @@ static void msmfb_suspend(struct early_suspend *h)
|
||||
overlay_event.event_wait,
|
||||
(overlay_event.waked_up == ~USE_OVERLAY),
|
||||
10*HZ);
|
||||
/*wait until USE_OVERLAY flag is off and set mdpclk_on as off*/
|
||||
atomic_set(&mdpclk_on, 0);
|
||||
pr_info("wait event : %X\n", overlay_event.waked_up);
|
||||
#endif
|
||||
panel->suspend(panel);
|
||||
@ -523,17 +567,81 @@ static void msmfb_suspend(struct early_suspend *h)
|
||||
static void msmfb_resume_handler(struct early_suspend *h)
|
||||
{
|
||||
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
|
||||
early_suspend);
|
||||
early_suspend);
|
||||
#ifdef CONFIG_HTC_ONMODE_CHARGING
|
||||
if (msmfb->fb_resumed == 1) {
|
||||
DLOG(SUSPEND_RESUME, "fb is resumed by onchg. skip resume\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
queue_work(msmfb->resume_workqueue, &msmfb->msmfb_resume_work);
|
||||
wait_event_interruptible_timeout(msmfb->frame_wq, msmfb->fb_resumed==1,HZ/2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HTC_ONMODE_CHARGING
|
||||
static void msmfb_onchg_earlier_suspend(struct early_suspend *h)
|
||||
{
|
||||
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
|
||||
onchg_earlier_suspend);
|
||||
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
mutex_lock(&msmfb->panel_init_lock);
|
||||
msmfb->sleeping = SLEEPING;
|
||||
wake_up(&msmfb->frame_wq);
|
||||
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
|
||||
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
|
||||
|
||||
#ifndef CONFIG_MSM_MDP40
|
||||
mdp->dma(mdp, virt_to_phys(msmfb->black), 0,
|
||||
msmfb->fb->var.xres, msmfb->fb->var.yres, 0, 0,
|
||||
NULL, panel->interface_type);
|
||||
mdp->dma_wait(mdp, panel->interface_type);
|
||||
#endif
|
||||
wait_event_timeout(msmfb->frame_wq,
|
||||
msmfb->frame_requested == msmfb->frame_done, HZ/10);
|
||||
|
||||
/* turn off the panel */
|
||||
panel->blank(panel);
|
||||
}
|
||||
|
||||
static void msmfb_onchg_suspend(struct early_suspend *h)
|
||||
{
|
||||
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
|
||||
onchg_suspend);
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
/* suspend the panel */
|
||||
#ifdef CONFIG_FB_MSM_OVERLAY
|
||||
/*check whether overlay done*/
|
||||
wait_event_interruptible_timeout(
|
||||
overlay_event.event_wait,
|
||||
(overlay_event.waked_up == ~USE_OVERLAY),
|
||||
10*HZ);
|
||||
/*wait until USE_OVERLAY flag is off and set mdpclk_on as off*/
|
||||
atomic_set(&mdpclk_on, 0);
|
||||
pr_info("wait event : %X\n", overlay_event.waked_up);
|
||||
#endif
|
||||
panel->suspend(panel);
|
||||
msmfb->fb_resumed = 0;
|
||||
mutex_unlock(&msmfb->panel_init_lock);
|
||||
}
|
||||
|
||||
static void msmfb_onchg_resume_handler(struct early_suspend *h)
|
||||
{
|
||||
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
|
||||
onchg_suspend);
|
||||
queue_work(msmfb->resume_workqueue, &msmfb->msmfb_resume_work);
|
||||
wait_event_interruptible_timeout(msmfb->frame_wq, msmfb->fb_resumed == 1, HZ/2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void msmfb_resume(struct work_struct *work)
|
||||
{
|
||||
struct msmfb_info *msmfb =
|
||||
container_of(work, struct msmfb_info, msmfb_resume_work);
|
||||
struct msm_panel_data *panel = msmfb->panel;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
if (panel->resume(panel)) {
|
||||
printk(KERN_INFO "msmfb: panel resume failed, not resuming "
|
||||
@ -545,15 +653,16 @@ static void msmfb_resume(struct work_struct *work)
|
||||
msmfb->sleeping = WAKING;
|
||||
DLOG(SUSPEND_RESUME, "ready, waiting for full update\n");
|
||||
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
|
||||
start_drawing_late_resume(NULL);
|
||||
msmfb->fb_resumed = 1;
|
||||
wake_up(&msmfb->frame_wq);
|
||||
|
||||
atomic_set(&mdpclk_on, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
u32 size;
|
||||
uint32_t size;
|
||||
|
||||
if ((var->xres != info->var.xres) ||
|
||||
(var->yres != info->var.yres) ||
|
||||
@ -625,28 +734,22 @@ int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
|
||||
{
|
||||
cfb_fillrect(p, rect);
|
||||
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
|
||||
msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
|
||||
rect->dy + rect->height);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
|
||||
{
|
||||
cfb_copyarea(p, area);
|
||||
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
|
||||
msmfb_update(p, area->dx, area->dy, area->dx + area->width,
|
||||
area->dy + area->height);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
|
||||
{
|
||||
cfb_imageblit(p, image);
|
||||
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
|
||||
msmfb_update(p, image->dx, image->dy, image->dx + image->width,
|
||||
image->dy + image->height);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -705,6 +808,7 @@ static int msmfb_overlay_set(struct fb_info *info, void __user *p)
|
||||
if (copy_from_user(&req, p, sizeof(req)))
|
||||
return -EFAULT;
|
||||
|
||||
printk(KERN_INFO "%s(%d) dst rect info w=%d h=%d x=%d y=%d rotator=%d\n", __func__, __LINE__, req.dst_rect.w, req.dst_rect.h, req.dst_rect.x, req.dst_rect.y, req.user_data[0]);
|
||||
ret = mdp->overlay_set(mdp, info, &req);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s:ioctl failed \n",
|
||||
@ -764,7 +868,7 @@ DEFINE_MUTEX(mdp_ppp_lock);
|
||||
static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
#if PRINT_BLIT_TIME
|
||||
ktime_t t1, t2;
|
||||
#endif
|
||||
@ -788,41 +892,41 @@ static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
#ifdef CONFIG_FB_MSM_OVERLAY
|
||||
case MSMFB_OVERLAY_GET:
|
||||
printk("CONFIG_FB_MSM_OVERLAY\n");
|
||||
//down(&mdp_ppp_lock);
|
||||
ret = msmfb_overlay_get(p, argp);
|
||||
//up(&mdp_ppp_lock);
|
||||
break;
|
||||
case MSMFB_OVERLAY_SET:
|
||||
printk("MSMFB_OVERLAY_SET\n");
|
||||
//down(&mdp_ppp_lock);
|
||||
ret = msmfb_overlay_set(p, argp);
|
||||
mutex_lock(&overlay_event_lock);
|
||||
overlay_event.waked_up = USE_OVERLAY;
|
||||
mutex_unlock(&overlay_event_lock);
|
||||
//up(&mdp_ppp_lock);
|
||||
if(!atomic_read(&mdpclk_on)) {
|
||||
printk(KERN_ERR "MSMFB_OVERLAY_SET during suspend\n");
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
mutex_lock(&overlay_event_lock);
|
||||
overlay_event.waked_up = USE_OVERLAY;
|
||||
mutex_unlock(&overlay_event_lock);
|
||||
ret = msmfb_overlay_set(p, argp);
|
||||
}
|
||||
printk(KERN_INFO "MSMFB_OVERLAY_SET ret=%d\n", ret);
|
||||
break;
|
||||
case MSMFB_OVERLAY_UNSET:
|
||||
printk("MSMFB_OVERLAY_UNSET\n");
|
||||
//down(&mdp_ppp_lock);
|
||||
ret = msmfb_overlay_unset(p, argp);
|
||||
mutex_lock(&overlay_event_lock);
|
||||
overlay_event.waked_up = ~USE_OVERLAY;
|
||||
wake_up(&overlay_event.event_wait);
|
||||
mutex_unlock(&overlay_event_lock);
|
||||
//up(&mdp_ppp_lock);
|
||||
printk(KERN_INFO "MSMFB_OVERLAY_UNSET ret=%d\n", ret);
|
||||
break;
|
||||
case MSMFB_OVERLAY_PLAY:
|
||||
//down(&mdp_ppp_lock);
|
||||
ret = msmfb_overlay_play(p, argp);
|
||||
//up(&mdp_ppp_lock);
|
||||
if(!atomic_read(&mdpclk_on)) {
|
||||
printk(KERN_ERR "MSMFB_OVERLAY_PLAY during suspend\n");
|
||||
ret = -EINVAL;
|
||||
} else
|
||||
ret = msmfb_overlay_play(p, argp);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct fb_ops msmfb_ops = {
|
||||
@ -856,7 +960,7 @@ static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
|
||||
static char buffer[4096];
|
||||
int n = 0;
|
||||
struct msmfb_info *msmfb = (struct msmfb_info *)file->private_data;
|
||||
unsigned long irq_flags;
|
||||
unsigned long irq_flags=0;
|
||||
|
||||
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
|
||||
n = scnprintf(buffer, debug_bufmax, "yoffset %d\n", msmfb->yoffset);
|
||||
@ -880,7 +984,7 @@ static struct file_operations debug_fops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define BITS_PER_PIXEL 16
|
||||
#define BITS_PER_PIXEL_DEF 32
|
||||
|
||||
static void setup_fb_info(struct msmfb_info *msmfb)
|
||||
{
|
||||
@ -904,8 +1008,9 @@ static void setup_fb_info(struct msmfb_info *msmfb)
|
||||
fb_info->var.height = msmfb->panel->fb_data->height;
|
||||
fb_info->var.xres_virtual = msmfb->xres;
|
||||
fb_info->var.yres_virtual = msmfb->yres * 2;
|
||||
fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
|
||||
fb_info->var.bits_per_pixel = BITS_PER_PIXEL_DEF;
|
||||
fb_info->var.accel_flags = 0;
|
||||
fb_info->var.reserved[4] = 60;
|
||||
|
||||
fb_info->var.yoffset = 0;
|
||||
|
||||
@ -938,6 +1043,7 @@ static void setup_fb_info(struct msmfb_info *msmfb)
|
||||
fb_info->var.blue.msb_right = 0;
|
||||
|
||||
mdp->set_output_format(mdp, fb_info->var.bits_per_pixel);
|
||||
mdp->set_panel_size(mdp, msmfb->xres, msmfb->yres);
|
||||
|
||||
r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
|
||||
fb_info->pseudo_palette = PP;
|
||||
@ -1027,7 +1133,7 @@ static int msmfb_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&msmfb->update_lock);
|
||||
mutex_init(&msmfb->panel_init_lock);
|
||||
init_waitqueue_head(&msmfb->frame_wq);
|
||||
msmfb->resume_workqueue = create_rt_workqueue("panel_on");
|
||||
msmfb->resume_workqueue = create_workqueue("panel_on");
|
||||
if (msmfb->resume_workqueue == NULL) {
|
||||
printk(KERN_ERR "failed to create panel_on workqueue\n");
|
||||
ret = -ENOMEM;
|
||||
@ -1049,6 +1155,16 @@ static int msmfb_probe(struct platform_device *pdev)
|
||||
msmfb->earlier_suspend.suspend = msmfb_earlier_suspend;
|
||||
msmfb->earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
|
||||
register_early_suspend(&msmfb->earlier_suspend);
|
||||
#ifdef CONFIG_HTC_ONMODE_CHARGING
|
||||
msmfb->onchg_suspend.suspend = msmfb_onchg_suspend;
|
||||
msmfb->onchg_suspend.resume = msmfb_onchg_resume_handler;
|
||||
msmfb->onchg_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
|
||||
register_onchg_suspend(&msmfb->onchg_suspend);
|
||||
|
||||
msmfb->onchg_earlier_suspend.suspend = msmfb_onchg_earlier_suspend;
|
||||
msmfb->onchg_earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
|
||||
register_onchg_suspend(&msmfb->onchg_earlier_suspend);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSMFB_DEBUG
|
||||
@ -1082,10 +1198,10 @@ static int msmfb_probe(struct platform_device *pdev)
|
||||
#ifdef CONFIG_FB_MSM_LOGO
|
||||
if (!load_565rle_image(INIT_IMAGE_FILE)) {
|
||||
/* Flip buffer */
|
||||
msmfb->update_info.left = 0;
|
||||
msmfb->update_info.left = 0;
|
||||
msmfb->update_info.top = 0;
|
||||
msmfb->update_info.eright = msmfb->xres;
|
||||
msmfb->update_info.ebottom = msmfb->yres;
|
||||
msmfb->update_info.ebottom = msmfb->yres;
|
||||
msmfb_pan_update(msmfb->fb, 0, 0, msmfb->xres,
|
||||
msmfb->yres, 0, 1);
|
||||
}
|
||||
|
@ -3,13 +3,31 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
struct dentry;
|
||||
|
||||
/* Definitions of frame buffers */
|
||||
|
||||
#define FB_MAX 32 /* sufficient for now */
|
||||
|
||||
struct fbcon_decor_iowrapper
|
||||
{
|
||||
unsigned short vc; /* Virtual console */
|
||||
unsigned char origin; /* Point of origin of the request */
|
||||
void *data;
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_COMPAT
|
||||
#include <linux/compat.h>
|
||||
struct fbcon_decor_iowrapper32
|
||||
{
|
||||
unsigned short vc; /* Virtual console */
|
||||
unsigned char origin; /* Point of origin of the request */
|
||||
compat_uptr_t data;
|
||||
};
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/* ioctls
|
||||
0x46 is 'F' */
|
||||
#define FBIOGET_VSCREENINFO 0x4600
|
||||
@ -37,7 +55,24 @@ struct dentry;
|
||||
#define FBIOGET_HWCINFO 0x4616
|
||||
#define FBIOPUT_MODEINFO 0x4617
|
||||
#define FBIOGET_DISPINFO 0x4618
|
||||
#define FBIOCONDECOR_SETCFG _IOWR('F', 0x19, struct fbcon_decor_iowrapper)
|
||||
#define FBIOCONDECOR_GETCFG _IOR('F', 0x1A, struct fbcon_decor_iowrapper)
|
||||
#define FBIOCONDECOR_SETSTATE _IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
|
||||
#define FBIOCONDECOR_GETSTATE _IOR('F', 0x1C, struct fbcon_decor_iowrapper)
|
||||
#define FBIOCONDECOR_SETPIC _IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define FBIOCONDECOR_SETCFG32 _IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
|
||||
#define FBIOCONDECOR_GETCFG32 _IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
|
||||
#define FBIOCONDECOR_SETSTATE32 _IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
|
||||
#define FBIOCONDECOR_GETSTATE32 _IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
|
||||
#define FBIOCONDECOR_SETPIC32 _IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#define FBCON_DECOR_THEME_LEN 128 /* Maximum lenght of a theme name */
|
||||
#define FBCON_DECOR_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */
|
||||
#define FBCON_DECOR_IO_ORIG_USER 1 /* User ioctl origin */
|
||||
|
||||
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
|
||||
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
|
||||
@ -282,6 +317,28 @@ struct fb_cmap {
|
||||
__u16 *transp; /* transparency, can be NULL */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct fb_cmap32 {
|
||||
__u32 start;
|
||||
__u32 len; /* Number of entries */
|
||||
compat_uptr_t red; /* Red values */
|
||||
compat_uptr_t green;
|
||||
compat_uptr_t blue;
|
||||
compat_uptr_t transp; /* transparency, can be NULL */
|
||||
};
|
||||
|
||||
#define fb_cmap_from_compat(to, from) \
|
||||
(to).start = (from).start; \
|
||||
(to).len = (from).len; \
|
||||
(to).red = compat_ptr((from).red); \
|
||||
(to).green = compat_ptr((from).green); \
|
||||
(to).blue = compat_ptr((from).blue); \
|
||||
(to).transp = compat_ptr((from).transp)
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
struct fb_con2fbmap {
|
||||
__u32 console;
|
||||
__u32 framebuffer;
|
||||
@ -363,6 +420,34 @@ struct fb_image {
|
||||
struct fb_cmap cmap; /* color map info */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct fb_image32 {
|
||||
__u32 dx; /* Where to place image */
|
||||
__u32 dy;
|
||||
__u32 width; /* Size of image */
|
||||
__u32 height;
|
||||
__u32 fg_color; /* Only used when a mono bitmap */
|
||||
__u32 bg_color;
|
||||
__u8 depth; /* Depth of the image */
|
||||
const compat_uptr_t data; /* Pointer to image data */
|
||||
struct fb_cmap32 cmap; /* color map info */
|
||||
};
|
||||
|
||||
#define fb_image_from_compat(to, from) \
|
||||
(to).dx = (from).dx; \
|
||||
(to).dy = (from).dy; \
|
||||
(to).width = (from).width; \
|
||||
(to).height = (from).height; \
|
||||
(to).fg_color = (from).fg_color; \
|
||||
(to).bg_color = (from).bg_color; \
|
||||
(to).depth = (from).depth; \
|
||||
(to).data = compat_ptr((from).data); \
|
||||
fb_cmap_from_compat((to).cmap, (from).cmap)
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* hardware cursor control
|
||||
*/
|
||||
@ -403,6 +488,7 @@ struct fb_cursor {
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct vm_area_struct;
|
||||
@ -543,6 +629,8 @@ struct fb_cursor_user {
|
||||
#define FB_EVENT_GET_REQ 0x0D
|
||||
/* Unbind from the console if possible */
|
||||
#define FB_EVENT_FB_UNBIND 0x0E
|
||||
/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */
|
||||
#define FB_EVENT_REMAP_ALL_CONSOLE 0x0F
|
||||
|
||||
struct fb_event {
|
||||
struct fb_info *info;
|
||||
@ -606,6 +694,12 @@ struct fb_deferred_io {
|
||||
* LOCKING NOTE: those functions must _ALL_ be called with the console
|
||||
* semaphore held, this is the only suitable locking mechanism we have
|
||||
* in 2.6. Some may be called at interrupt time at this point though.
|
||||
*
|
||||
* The exception to this is the debug related hooks. Putting the fb
|
||||
* into a debug state (e.g. flipping to the kernel console) and restoring
|
||||
* it must be done in a lock-free manner, so low level drivers should
|
||||
* keep track of the initial console (if applicable) and may need to
|
||||
* perform direct, unlocked hardware writes in these hooks.
|
||||
*/
|
||||
|
||||
struct fb_ops {
|
||||
@ -675,6 +769,10 @@ struct fb_ops {
|
||||
|
||||
/* teardown any resources to do with this framebuffer */
|
||||
void (*fb_destroy)(struct fb_info *info);
|
||||
|
||||
/* called at KDB enter and leave time to prepare the console */
|
||||
int (*fb_debug_enter)(struct fb_info *info);
|
||||
int (*fb_debug_leave)(struct fb_info *info);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_FB_TILEBLITTING
|
||||
@ -763,6 +861,7 @@ struct fb_tile_ops {
|
||||
* takes over; acceleration engine should be in a quiescent state */
|
||||
|
||||
/* hints */
|
||||
#define FBINFO_VIRTFB 0x0004 /* FB is System RAM, not device. */
|
||||
#define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */
|
||||
#define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */
|
||||
|
||||
@ -784,8 +883,6 @@ struct fb_tile_ops {
|
||||
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
|
||||
from userspace */
|
||||
#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
|
||||
#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware
|
||||
inited framebuffer */
|
||||
|
||||
/* A driver may set this flag to indicate that it does want a set_par to be
|
||||
* called every time when fbcon_switch is executed. The advantage is that with
|
||||
@ -799,6 +896,8 @@ struct fb_tile_ops {
|
||||
*/
|
||||
#define FBINFO_MISC_ALWAYS_SETPAR 0x40000
|
||||
|
||||
/* where the fb is a firmware driver, and can be replaced with a proper one */
|
||||
#define FBINFO_MISC_FIRMWARE 0x80000
|
||||
/*
|
||||
* Host and GPU endianness differ.
|
||||
*/
|
||||
@ -810,6 +909,10 @@ struct fb_tile_ops {
|
||||
*/
|
||||
#define FBINFO_BE_MATH 0x100000
|
||||
|
||||
/* report to the VT layer that this fb driver can accept forced console
|
||||
output like oopses */
|
||||
#define FBINFO_CAN_FORCE_OUTPUT 0x200000
|
||||
|
||||
struct fb_info {
|
||||
int node;
|
||||
int flags;
|
||||
@ -854,15 +957,32 @@ struct fb_info {
|
||||
#define FBINFO_STATE_SUSPENDED 1
|
||||
u32 state; /* Hardware state i.e suspend */
|
||||
void *fbcon_par; /* fbcon use-only private area */
|
||||
|
||||
struct fb_image bgdecor;
|
||||
|
||||
/* From here on everything is device dependent */
|
||||
void *par;
|
||||
/* we need the PCI or similiar aperture base/size not
|
||||
smem_start/size as smem_start may just be an object
|
||||
allocated inside the aperture so may not actually overlap */
|
||||
resource_size_t aperture_base;
|
||||
resource_size_t aperture_size;
|
||||
struct apertures_struct {
|
||||
unsigned int count;
|
||||
struct aperture {
|
||||
resource_size_t base;
|
||||
resource_size_t size;
|
||||
} ranges[0];
|
||||
} *apertures;
|
||||
};
|
||||
|
||||
static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
|
||||
struct apertures_struct *a = kzalloc(sizeof(struct apertures_struct)
|
||||
+ max_num * sizeof(struct aperture), GFP_KERNEL);
|
||||
if (!a)
|
||||
return NULL;
|
||||
a->count = max_num;
|
||||
return a;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
#define FBINFO_DEFAULT FBINFO_MODULE
|
||||
#else
|
||||
@ -898,6 +1018,8 @@ struct fb_info {
|
||||
#define fb_writel sbus_writel
|
||||
#define fb_writeq sbus_writeq
|
||||
#define fb_memset sbus_memset_io
|
||||
#define fb_memcpy_fromfb sbus_memcpy_fromio
|
||||
#define fb_memcpy_tofb sbus_memcpy_toio
|
||||
|
||||
#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || defined(__avr32__) || defined(__bfin__)
|
||||
|
||||
@ -910,6 +1032,8 @@ struct fb_info {
|
||||
#define fb_writel __raw_writel
|
||||
#define fb_writeq __raw_writeq
|
||||
#define fb_memset memset_io
|
||||
#define fb_memcpy_fromfb memcpy_fromio
|
||||
#define fb_memcpy_tofb memcpy_toio
|
||||
|
||||
#else
|
||||
|
||||
@ -922,6 +1046,8 @@ struct fb_info {
|
||||
#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b))
|
||||
#define fb_writeq(b,addr) (*(volatile u64 *) (addr) = (b))
|
||||
#define fb_memset memset
|
||||
#define fb_memcpy_fromfb memcpy
|
||||
#define fb_memcpy_tofb memcpy
|
||||
|
||||
#endif
|
||||
|
||||
@ -955,6 +1081,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
|
||||
/* drivers/video/fbmem.c */
|
||||
extern int register_framebuffer(struct fb_info *fb_info);
|
||||
extern int unregister_framebuffer(struct fb_info *fb_info);
|
||||
extern void remove_conflicting_framebuffers(struct apertures_struct *a,
|
||||
const char *name, bool primary);
|
||||
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
|
||||
extern int fb_show_logo(struct fb_info *fb_info, int rotate);
|
||||
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
|
||||
@ -1052,6 +1180,8 @@ extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
|
||||
extern const unsigned char *fb_firmware_edid(struct device *device);
|
||||
extern void fb_edid_to_monspecs(unsigned char *edid,
|
||||
struct fb_monspecs *specs);
|
||||
extern void fb_edid_add_monspecs(unsigned char *edid,
|
||||
struct fb_monspecs *specs);
|
||||
extern void fb_destroy_modedb(struct fb_videomode *modedb);
|
||||
extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
|
||||
extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
|
||||
@ -1082,6 +1212,7 @@ extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs
|
||||
|
||||
/* drivers/video/fbcmap.c */
|
||||
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
|
||||
extern int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags);
|
||||
extern void fb_dealloc_cmap(struct fb_cmap *cmap);
|
||||
extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to);
|
||||
extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to);
|
||||
|
209
include/linux/msm_audio_1550.h
Normal file
209
include/linux/msm_audio_1550.h
Normal file
@ -0,0 +1,209 @@
|
||||
/* include/linux/msm_audio.h
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MSM_AUDIO_H
|
||||
#define __LINUX_MSM_AUDIO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
/* PCM Audio */
|
||||
|
||||
#define AUDIO_IOCTL_MAGIC 'a'
|
||||
|
||||
#define AUDIO_ENABLE_AUDPRE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
|
||||
#define AUDIO_SET_AGC _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned)
|
||||
#define AUDIO_SET_NS _IOW(AUDIO_IOCTL_MAGIC, 13, unsigned)
|
||||
#define AUDIO_SET_TX_IIR _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
|
||||
#define AUDIO_PLAY_DTMF _IOW(AUDIO_IOCTL_MAGIC, 19, unsigned)
|
||||
|
||||
#define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
|
||||
#define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
|
||||
#define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
|
||||
#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
|
||||
#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
|
||||
#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
|
||||
#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned)
|
||||
#define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned)
|
||||
#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned)
|
||||
#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned)
|
||||
#define AUDIO_SET_VOLUME _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned)
|
||||
#define AUDIO_PAUSE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
|
||||
#define AUDIO_GET_EVENT _IOR(AUDIO_IOCTL_MAGIC, 13, unsigned)
|
||||
#define AUDIO_ABORT_GET_EVENT _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
|
||||
#define AUDIO_REGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 15, unsigned)
|
||||
#define AUDIO_DEREGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 16, unsigned)
|
||||
#define AUDIO_WAIT_ADSP_DONE _IOR(AUDIO_IOCTL_MAGIC, 16, unsigned)
|
||||
#define AUDIO_ADSP_PAUSE _IOR(AUDIO_IOCTL_MAGIC, 17, unsigned)
|
||||
#define AUDIO_ASYNC_WRITE _IOW(AUDIO_IOCTL_MAGIC, 17, unsigned)
|
||||
#define AUDIO_ADSP_RESUME _IOR(AUDIO_IOCTL_MAGIC, 18, unsigned)
|
||||
#define AUDIO_ASYNC_READ _IOW(AUDIO_IOCTL_MAGIC, 18, unsigned)
|
||||
#define AUDIO_SET_INCALL _IOW(AUDIO_IOCTL_MAGIC, 19, \
|
||||
struct msm_voicerec_mode)
|
||||
#define AUDIO_GET_NUM_SND_DEVICE _IOR(AUDIO_IOCTL_MAGIC, 20, unsigned)
|
||||
#define AUDIO_GET_AMRNB_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 21, unsigned)
|
||||
#define AUDIO_GET_SND_DEVICES _IOWR(AUDIO_IOCTL_MAGIC, 21, \
|
||||
struct msm_snd_device_list)
|
||||
#define AUDIO_SET_AMRNB_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 22, unsigned)
|
||||
#define AUDIO_ENABLE_SND_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 22, unsigned)
|
||||
#define AUDIO_DISABLE_SND_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 23, unsigned)
|
||||
#define AUDIO_ROUTE_STREAM _IOW(AUDIO_IOCTL_MAGIC, 24, \
|
||||
struct msm_audio_route_config)
|
||||
#define AUDIO_GET_PCM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 30, unsigned)
|
||||
#define AUDIO_SET_PCM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 31, unsigned)
|
||||
#define AUDIO_SWITCH_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 32, unsigned)
|
||||
#define AUDIO_SET_MUTE _IOW(AUDIO_IOCTL_MAGIC, 33, unsigned)
|
||||
#define AUDIO_UPDATE_ACDB _IOW(AUDIO_IOCTL_MAGIC, 34, unsigned)
|
||||
#define AUDIO_START_VOICE _IOW(AUDIO_IOCTL_MAGIC, 35, unsigned)
|
||||
#define AUDIO_STOP_VOICE _IOW(AUDIO_IOCTL_MAGIC, 36, unsigned)
|
||||
#define AUDIO_START_FM _IOW(AUDIO_IOCTL_MAGIC, 37, unsigned)
|
||||
#define AUDIO_STOP_FM _IOW(AUDIO_IOCTL_MAGIC, 38, unsigned)
|
||||
#define AUDIO_REINIT_ACDB _IOW(AUDIO_IOCTL_MAGIC, 39, unsigned)
|
||||
#define AUDIO_ENABLE_AUXPGA_LOOPBACK _IOW(AUDIO_IOCTL_MAGIC, 40, unsigned)
|
||||
#define AUDIO_OUTPORT_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 40, \
|
||||
unsigned short)
|
||||
#define AUDIO_SET_AUXPGA_GAIN _IOW(AUDIO_IOCTL_MAGIC, 41, unsigned)
|
||||
#define AUDIO_SET_ERR_THRESHOLD_VALUE _IOW(AUDIO_IOCTL_MAGIC, 41, \
|
||||
unsigned short)
|
||||
#define AUDIO_SET_RX_MUTE _IOW(AUDIO_IOCTL_MAGIC, 42, unsigned)
|
||||
#define AUDIO_GET_BITSTREAM_ERROR_INFO _IOR(AUDIO_IOCTL_MAGIC, 42, \
|
||||
struct msm_audio_bitstream_error_info)
|
||||
|
||||
/* Qualcomm extensions */
|
||||
#define AUDIO_SET_STREAM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 80, \
|
||||
struct msm_audio_stream_config)
|
||||
#define AUDIO_GET_STREAM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 81, \
|
||||
struct msm_audio_stream_config)
|
||||
#define AUDIO_GET_SESSION_ID _IOR(AUDIO_IOCTL_MAGIC, 82, \
|
||||
unsigned short)
|
||||
#define AUDIO_GET_STREAM_INFO _IOR(AUDIO_IOCTL_MAGIC, 83, \
|
||||
struct msm_audio_bitstream_info)
|
||||
#define AUDIO_SET_PAN _IOW(AUDIO_IOCTL_MAGIC, 84, unsigned)
|
||||
#define AUDIO_SET_QCONCERT_PLUS _IOW(AUDIO_IOCTL_MAGIC, 85, unsigned)
|
||||
#define AUDIO_SET_MBADRC _IOW(AUDIO_IOCTL_MAGIC, 86, unsigned)
|
||||
#define AUDIO_SET_VOLUME_PATH _IOW(AUDIO_IOCTL_MAGIC, 87, \
|
||||
struct msm_vol_info)
|
||||
#define AUDIO_SET_MAX_VOL_ALL _IOW(AUDIO_IOCTL_MAGIC, 88, unsigned)
|
||||
#define AUDIO_GET_BUF_CFG _IOW(AUDIO_IOCTL_MAGIC, 93, \
|
||||
struct msm_audio_buf_cfg)
|
||||
#define AUDIO_SET_BUF_CFG _IOW(AUDIO_IOCTL_MAGIC, 94, \
|
||||
struct msm_audio_buf_cfg)
|
||||
#define AUDIO_SET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 95, \
|
||||
struct msm_acdb_cmd_device)
|
||||
#define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96, \
|
||||
struct msm_acdb_cmd_device)
|
||||
|
||||
#define AUDIO_MAX_COMMON_IOCTL_NUM 100
|
||||
|
||||
struct msm_audio_config {
|
||||
uint32_t buffer_size;
|
||||
uint32_t buffer_count;
|
||||
uint32_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
uint32_t type;
|
||||
uint32_t unused[3];
|
||||
};
|
||||
|
||||
struct msm_audio_stats {
|
||||
uint32_t byte_count;
|
||||
uint32_t sample_count;
|
||||
uint32_t unused[2];
|
||||
};
|
||||
|
||||
struct msm_mute_info {
|
||||
uint32_t mute;
|
||||
uint32_t path;
|
||||
};
|
||||
|
||||
#define AAC_OBJECT_ER_LC 17
|
||||
#define AAC_OBJECT_ER_LTP 19
|
||||
#define AAC_OBJECT_ER_SCALABLE 20
|
||||
#define AAC_OBJECT_BSAC 22
|
||||
#define AAC_OBJECT_ER_LD 23
|
||||
|
||||
struct aac_format {
|
||||
uint16_t sample_rate;
|
||||
uint16_t channel_config;
|
||||
uint16_t block_formats;
|
||||
uint16_t audio_object_type;
|
||||
uint16_t ep_config;
|
||||
uint16_t aac_section_data_resilience_flag;
|
||||
uint16_t aac_scalefactor_data_resilience_flag;
|
||||
uint16_t aac_spectral_data_resilience_flag;
|
||||
uint16_t sbr_on_flag;
|
||||
uint16_t sbr_ps_on_flag;
|
||||
uint32_t bit_rate;
|
||||
};
|
||||
|
||||
struct msm_audio_stream_config {
|
||||
uint32_t buffer_size;
|
||||
uint32_t buffer_count;
|
||||
};
|
||||
|
||||
/* Audio routing */
|
||||
|
||||
#define SND_IOCTL_MAGIC 's'
|
||||
|
||||
#define SND_MUTE_UNMUTED 0
|
||||
#define SND_MUTE_MUTED 1
|
||||
|
||||
struct msm_voicerec_mode {
|
||||
uint32_t rec_mode;
|
||||
};
|
||||
|
||||
struct msm_snd_device_config {
|
||||
uint32_t device;
|
||||
uint32_t ear_mute;
|
||||
uint32_t mic_mute;
|
||||
};
|
||||
|
||||
#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
|
||||
|
||||
#define SND_METHOD_VOICE 0
|
||||
|
||||
struct msm_snd_volume_config {
|
||||
uint32_t device;
|
||||
uint32_t method;
|
||||
uint32_t volume;
|
||||
};
|
||||
|
||||
#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
|
||||
|
||||
/* Returns the number of SND endpoints supported. */
|
||||
|
||||
#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
|
||||
|
||||
struct msm_snd_endpoint {
|
||||
int id; /* input and output */
|
||||
char name[64]; /* output only */
|
||||
};
|
||||
|
||||
/* Takes an index between 0 and one less than the number returned by
|
||||
* SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a
|
||||
* SND endpoint. On input, the .id field contains the number of the
|
||||
* endpoint, and on exit it contains the SND index, while .name contains
|
||||
* the description of the endpoint.
|
||||
*/
|
||||
|
||||
#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *)
|
||||
|
||||
struct msm_audio_pcm_config {
|
||||
uint32_t pcm_feedback; /* 0 - disable > 0 - enable */
|
||||
uint32_t buffer_count; /* Number of buffers to allocate */
|
||||
uint32_t buffer_size; /* Size of buffer for capturing of
|
||||
PCM samples */
|
||||
};
|
||||
#endif
|
91
include/linux/msm_audio_aac.h
Normal file
91
include/linux/msm_audio_aac.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* arch/arm/mach-msm/include/mach/msm_audio_aac.h
|
||||
*
|
||||
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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, you can find it at http://www.fsf.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MSM_AUDIO_AAC_H
|
||||
#define __MSM_AUDIO_AAC_H
|
||||
|
||||
#include <linux/msm_audio_1550.h>
|
||||
|
||||
#define AUDIO_SET_AAC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
|
||||
(AUDIO_MAX_COMMON_IOCTL_NUM+0), unsigned)
|
||||
#define AUDIO_GET_AAC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \
|
||||
(AUDIO_MAX_COMMON_IOCTL_NUM+1), unsigned)
|
||||
|
||||
#define AUDIO_SET_AAC_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
|
||||
(AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config)
|
||||
|
||||
#define AUDIO_GET_AAC_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \
|
||||
(AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config)
|
||||
|
||||
#define AUDIO_AAC_FORMAT_ADTS -1
|
||||
#define AUDIO_AAC_FORMAT_RAW 0x0000
|
||||
#define AUDIO_AAC_FORMAT_PSUEDO_RAW 0x0001
|
||||
#define AUDIO_AAC_FORMAT_LOAS 0x0002
|
||||
#define AUDIO_AAC_FORMAT_ADIF 0x0003
|
||||
|
||||
|
||||
#define AUDIO_AAC_OBJECT_LC 0x0002
|
||||
#define AUDIO_AAC_OBJECT_LTP 0x0004
|
||||
#define AUDIO_AAC_OBJECT_ERLC 0x0011
|
||||
#define AUDIO_AAC_OBJECT_BSAC 0x0016
|
||||
|
||||
#define AUDIO_AAC_SEC_DATA_RES_ON 0x0001
|
||||
#define AUDIO_AAC_SEC_DATA_RES_OFF 0x0000
|
||||
|
||||
#define AUDIO_AAC_SCA_DATA_RES_ON 0x0001
|
||||
#define AUDIO_AAC_SCA_DATA_RES_OFF 0x0000
|
||||
|
||||
#define AUDIO_AAC_SPEC_DATA_RES_ON 0x0001
|
||||
#define AUDIO_AAC_SPEC_DATA_RES_OFF 0x0000
|
||||
|
||||
#define AUDIO_AAC_SBR_ON_FLAG_ON 0x0001
|
||||
#define AUDIO_AAC_SBR_ON_FLAG_OFF 0x0000
|
||||
|
||||
#define AUDIO_AAC_SBR_PS_ON_FLAG_ON 0x0001
|
||||
#define AUDIO_AAC_SBR_PS_ON_FLAG_OFF 0x0000
|
||||
|
||||
/* Primary channel on both left and right channels */
|
||||
#define AUDIO_AAC_DUAL_MONO_PL_PR 0
|
||||
/* Secondary channel on both left and right channels */
|
||||
#define AUDIO_AAC_DUAL_MONO_SL_SR 1
|
||||
/* Primary channel on right channel and 2nd on left channel */
|
||||
#define AUDIO_AAC_DUAL_MONO_SL_PR 2
|
||||
/* 2nd channel on right channel and primary on left channel */
|
||||
#define AUDIO_AAC_DUAL_MONO_PL_SR 3
|
||||
|
||||
struct msm_audio_aac_config {
|
||||
signed short format;
|
||||
unsigned short audio_object;
|
||||
unsigned short ep_config; /* 0 ~ 3 useful only obj = ERLC */
|
||||
unsigned short aac_section_data_resilience_flag;
|
||||
unsigned short aac_scalefactor_data_resilience_flag;
|
||||
unsigned short aac_spectral_data_resilience_flag;
|
||||
unsigned short sbr_on_flag;
|
||||
unsigned short sbr_ps_on_flag;
|
||||
unsigned short dual_mono_mode;
|
||||
unsigned short channel_configuration;
|
||||
};
|
||||
|
||||
struct msm_audio_aac_enc_config {
|
||||
uint32_t channels;
|
||||
uint32_t sample_rate;
|
||||
uint32_t bit_rate;
|
||||
uint32_t stream_format;
|
||||
};
|
||||
|
||||
#endif /* __MSM_AUDIO_AAC_H */
|
@ -19,36 +19,21 @@
|
||||
#define MSMFB_IOCTL_MAGIC 'm'
|
||||
#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
|
||||
#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \
|
||||
struct mdp_overlay)
|
||||
#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
|
||||
#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \
|
||||
struct msmfb_overlay_data)
|
||||
#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \
|
||||
struct mdp_overlay)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
MDP_RGB_565, // RGB 565 planer
|
||||
MDP_XRGB_8888, // RGB 888 padded
|
||||
MDP_Y_CBCR_H2V2, // Y and CbCr, pseudo planer w/ Cb is in MSB
|
||||
MDP_ARGB_8888, // ARGB 888
|
||||
MDP_RGB_888, // RGB 888 planer
|
||||
MDP_Y_CRCB_H2V2, // Y and CrCb, pseudo planer w/ Cr is in MSB
|
||||
MDP_YCRYCB_H2V1, // YCrYCb interleave
|
||||
MDP_Y_CRCB_H2V1, // Y and CrCb, pseduo planer w/ Cr is in MSB
|
||||
MDP_Y_CBCR_H2V1, // Y and CrCb, pseduo planer w/ Cr is in MSB
|
||||
MDP_RGBA_8888, // ARGB 888
|
||||
MDP_BGRA_8888, // ARGB 888
|
||||
MDP_RGBX_8888, // RGBX 888
|
||||
MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */
|
||||
MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */
|
||||
MDP_IMGTYPE_LIMIT, // Non valid image type after this enum
|
||||
MDP_IMGTYPE2_START = 0x10000,
|
||||
MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
|
||||
MDP_FB_FORMAT, /* framebuffer format */
|
||||
MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
|
||||
MDP_RGB_565, /* RGB 565 planar */
|
||||
MDP_XRGB_8888, /* RGB 888 padded */
|
||||
MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planar w/ Cb is in MSB */
|
||||
MDP_ARGB_8888, /* ARGB 888 */
|
||||
MDP_RGB_888, /* RGB 888 planar */
|
||||
MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planar w/ Cr is in MSB */
|
||||
MDP_YCRYCB_H2V1, /* YCrYCb interleave */
|
||||
MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planar w/ Cr is in MSB */
|
||||
MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planar w/ Cr is in MSB */
|
||||
MDP_RGBA_8888, /* ARGB 888 */
|
||||
MDP_BGRA_8888, /* ABGR 888 */
|
||||
MDP_RGBX_8888, /* RGBX 888 */
|
||||
MDP_IMGTYPE_LIMIT /* Non valid image type after this enum */
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -57,20 +42,23 @@ enum {
|
||||
};
|
||||
|
||||
/* flag values */
|
||||
#define MDP_ROT_NOP 0
|
||||
#define MDP_FLIP_LR 0x1
|
||||
#define MDP_FLIP_UD 0x2
|
||||
#define MDP_ROT_90 0x4
|
||||
#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
|
||||
#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
|
||||
#define MDP_ROT_MASK 0x7
|
||||
#define MDP_DITHER 0x8
|
||||
#define MDP_BLUR 0x10
|
||||
#define MDP_ROT_NOP 0
|
||||
#define MDP_FLIP_LR 0x1
|
||||
#define MDP_FLIP_UD 0x2
|
||||
#define MDP_ROT_90 0x4
|
||||
#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
|
||||
#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
|
||||
#define MDP_ROT_MASK 0x7
|
||||
#define MDP_DITHER 0x8
|
||||
#define MDP_BLUR 0x10
|
||||
#define MDP_BLEND_FG_PREMULT 0x20000
|
||||
#define MDP_DEINTERLACE 0x80000000
|
||||
#define MDP_SHARPENING 0x40000000
|
||||
#define MDP_TRANSP_NOP 0xffffffff
|
||||
#define MDP_ALPHA_NOP 0xff
|
||||
|
||||
#define MDP_TRANSP_NOP 0xffffffff
|
||||
#define MDP_ALPHA_NOP 0xff
|
||||
|
||||
/* drewis: added for android 4.0 */
|
||||
#define MDP_BLIT_NON_CACHED 0x01000000
|
||||
/* drewis: end */
|
||||
|
||||
struct mdp_rect {
|
||||
uint32_t x;
|
||||
@ -95,7 +83,6 @@ struct mdp_blit_req {
|
||||
uint32_t alpha;
|
||||
uint32_t transp_mask;
|
||||
uint32_t flags;
|
||||
int sharpening_strength; /* -127 <--> 127, default 64 */
|
||||
};
|
||||
|
||||
struct mdp_blit_req_list {
|
||||
@ -103,37 +90,4 @@ struct mdp_blit_req_list {
|
||||
struct mdp_blit_req req[];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_MDP40
|
||||
struct msmfb_data {
|
||||
uint32_t offset;
|
||||
int memory_id;
|
||||
int id;
|
||||
};
|
||||
|
||||
#define MSMFB_NEW_REQUEST -1
|
||||
|
||||
struct msmfb_overlay_data {
|
||||
uint32_t id;
|
||||
struct msmfb_data data;
|
||||
};
|
||||
|
||||
struct msmfb_img {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t format;
|
||||
};
|
||||
|
||||
struct mdp_overlay {
|
||||
struct msmfb_img src;
|
||||
struct mdp_rect src_rect;
|
||||
struct mdp_rect dst_rect;
|
||||
uint32_t z_order; /* stage number */
|
||||
uint32_t is_fg; /* control alpha & transp */
|
||||
uint32_t alpha;
|
||||
uint32_t transp_mask;
|
||||
uint32_t flags;
|
||||
uint32_t id;
|
||||
uint32_t user_data[8];
|
||||
};
|
||||
#endif
|
||||
#endif //_MSM_MDP_H_
|
||||
#endif /* _MSM_MDP_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user