reg = <10>;
regulator-compatible = "act_ldo7";
regulator-always-on;
+ /* regulator-always-on; */
regulator-boot-on;
};
};
};
-};
\ No newline at end of file
+};
/dts-v1/;
-
+#include <dt-bindings/rkfb/rk_fb.h>
#include "rk3036.dtsi"
+#include "rk3036-pinctrl.dtsi"
+#include "lcd-box.dtsi"
+#include <dt-bindings/input/input.h>
/ {
pwms = <&pwm2 0 25000>;
rockchip,pwm_id= <2>;
rockchip,pwm_voltage_map= <950000 975000 1000000 1025000 1050000 1075000 1100000 1125000 1150000 1175000 1200000 1225000 1250000 1275000 1300000 1325000 1350000 1375000 1400000 1425000 1450000>;
- rockchip,pwm_voltage= <1250000>;
+ rockchip,pwm_voltage= <1300000>;
rockchip,pwm_min_voltage= <950000>;
rockchip,pwm_max_voltage= <1450000>;
- rockchip,pwm_suspend_voltage= <1250000>;
+ rockchip,pwm_suspend_voltage= <1000000>;
rockchip,pwm_coefficient= <500>;
- status = "disabled";
+ status = "okay";
regulators {
#address-cells = <1>;
#size-cells = <0>;
};
};
+ gpio_poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio1 GPIO_A2 GPIO_ACTIVE_LOW>;
+ };
+
wireless-wlan {
compatible = "wlan-platdata";
+
/* wifi_chip_type - wifi chip define
- * bcmwifi ==> like ap6xxx, rk90x, ...;
- * rtkwifi ==> like rtl8188xx, rtl8723xx, ...;
+ * bcmwifi ==> like ap6xxx, rk90x;
+ * rtkwifi ==> like rtl8188xx, rtl8723xx,rtl8812auv;
* esp8089 ==> esp8089;
* other ==> for other wifi;
*/
wifi_chip_type = "esp8089";
- sdio_vref = <1800>; //1800mv or 3300mv
+ sdio_vref = <0>; //1800mv or 3300mv
- //keep_wifi_power_on;
//power_ctrl_by_pmu;
+ //keep_wifi_power_on;
//power_pmu_regulator = "act_ldo3";
//power_pmu_enable_level = <1>; //1->HIGH, 0->LOW
//vref_pmu_regulator = "act_ldo3";
//vref_pmu_enable_level = <1>; //1->HIGH, 0->LOW
- //WIFI,poweren_gpio = <&gpio4 GPIO_D4 GPIO_ACTIVE_HIGH>;
- //WIFI,host_wake_irq = <&gpio4 GPIO_D6 GPIO_ACTIVE_HIGH>;
+ WIFI,poweren_gpio = <&gpio2 GPIO_D6 GPIO_ACTIVE_HIGH>;
+ WIFI,host_wake_irq = <&gpio2 GPIO_C4 GPIO_ACTIVE_HIGH>;
//WIFI,reset_gpio = <&gpio0 GPIO_A2 GPIO_ACTIVE_LOW>;
status = "okay";
};
-/* wireless-bluetooth {
+ /* wireless-bluetooth {
compatible = "bluetooth-platdata";
//wifi-bt-power-toggle;
};*/
+ usb_control {
+ compatible = "rockchip,rk3036-usb-control";
+ host_drv_gpio = <&gpio2 GPIO_C7 GPIO_ACTIVE_LOW>;
+ otg_drv_gpio = <&gpio0 GPIO_D2 GPIO_ACTIVE_LOW>;
+
+ rockchip,remote_wakeup;
+ rockchip,usb_irq_wakeup;
+ };
+
+ usb0: usb@10180000 {
+ /*0 - Normal, 1 - Force Host, 2 - Force Device*/
+ rockchip,usb-mode = <1>;
+ };
+
+ key {
+ compatible = "rockchip,key";
+ };
+
+ codec_hdmi_spdif: codec-hdmi-spdif {
+ compatible = "hdmi-spdif";
+ };
+
+ rockchip-hdmi-spdif {
+ compatible = "rockchip-hdmi-spdif";
+ dais {
+ dai0 {
+ audio-codec = <&codec_hdmi_spdif>;
+ i2s-controller = <&spdif>;
+ };
+ };
+ };
+
+ rockchip-spdif-card {
+ compatible = "rockchip-spdif-card";
+ dais {
+ dai0 {
+ audio-codec = <&codec_hdmi_spdif>;
+ i2s-controller = <&spdif>;
+ };
+ };
+ };
+
+ rockchip-audio {
+ compatible = "rk3036-audio";
+ dais {
+ dai0 {
+ audio-codec = <&codec>;
+ i2s-controller = <&i2s>;
+ format = "i2s";
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ //bitclock-master;
+ //frame-master;
+ };
+ };
+ };
+};
+
+&uart0{
+ status = "okay";
+ dma-names = "!tx", "!rx";
+ pinctrl-0 = <&uart0_xfer &uart0_cts>;
+};
&nandc {
+ status = "okay"; // used nand set "okay" ,used emmc set "disabled"
+};
+
+&nandc0reg {
status = "disabled"; // used nand set "disabled" ,used emmc set "okay"
-};
+};
&emmc {
- clock-frequency = <100000000>;
- clock-freq-min-max = <400000 100000000>;
+ clock-frequency = <37500000>;
+ clock-freq-min-max = <400000 37500000>;
supports-highspeed;
supports-emmc;
bootpart-no-access;
supports-DDR_MODE;
- //caps2-mmc-hs200;
ignore-pm-notify;
keep-power-in-suspend;
-
- //poll-hw-reset
- status = "okay";
+
+ //poll-hw-reset
+ status = "disabled";
};
-
+
&sdmmc {
- clock-frequency = <50000000>;
- clock-freq-min-max = <400000 50000000>;
+ clock-frequency = <37500000>;
+ clock-freq-min-max = <400000 37500000>;
supports-highspeed;
supports-sd;
broken-cd;
card-detect-delay = <200>;
ignore-pm-notify;
- keep-power-in-suspend;
-
- //vmmc-supply = <&rk808_ldo5_reg>;
+ keep-power-in-suspend;
+
+ //vmmc-supply = <&rk808_ldo5_reg>;
status = "okay";
};
-
+
&sdio {
- clock-frequency = <50000000>;
- clock-freq-min-max = <200000 50000000>;
+ clock-frequency = <37500000>;
+ clock-freq-min-max = <200000 37500000>;
supports-highspeed;
supports-sdio;
ignore-pm-notify;
keep-power-in-suspend;
- //cap-sdio-irq;
+ cap-sdio-irq;
status = "okay";
};
-&uart0 {
+
+&i2c1 {
status = "okay";
- dma-names = "!tx", "!rx";
- //pinctrl-0 = <&uart0_xfer &uart0_cts>;
+ rtc@51 {
+ compatible = "rtc,hym8563";
+ reg = <0x51>;
+ //irq_gpio = <&gpio0 GPIO_A4 IRQ_TYPE_EDGE_FALLING>;
+ };
};
+
&rk_screen {
display-timings = <&disp_timings>;
};
+&fb {
+ rockchip,disp-mode = <NO_DUAL>;
+ rockchip,uboot-logo-on = <1>;
+};
+
&lcdc {
status = "okay";
};
&tve {
- status = "disabled";
+ status = "okay";
};
&hdmi {
status = "okay";
//rockchips,hdmi_audio_source = <0>;
};
+
+&vmac {
+// pmu_regulator = "act_ldo5";
+// pmu_enable_level = <1>; //1->HIGH, 0->LOW
+// power-gpio = <&gpio0 GPIO_A6 GPIO_ACTIVE_HIGH>;
+ reset-gpio = <&gpio2 GPIO_C6 GPIO_ACTIVE_LOW>;
+};
+
+&dwc_control_usb {
+ usb_uart {
+ status = "disabled";
+ };
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&remotectl {
+ handle_cpu_id = <1>;
+ ir_key1{
+ rockchip,usercode = <0x4040>;
+ rockchip,key_table =
+ <0xf2 KEY_REPLY>,
+ <0xba KEY_BACK>,
+ <0xf4 KEY_UP>,
+ <0xf1 KEY_DOWN>,
+ <0xef KEY_LEFT>,
+ <0xee KEY_RIGHT>,
+ <0xbd KEY_HOME>,
+ <0xea KEY_VOLUMEUP>,
+ <0xe3 KEY_VOLUMEDOWN>,
+ <0xe2 KEY_SEARCH>,
+ <0xb2 KEY_POWER>,
+ <0xbc KEY_MUTE>,
+ <0xec KEY_MENU>,
+ <0xbf 0x190>,
+ <0xe0 0x191>,
+ <0xe1 0x192>,
+ <0xe9 183>,
+ <0xe6 248>,
+ <0xe8 185>,
+ <0xe7 186>,
+ <0xf0 388>,
+ <0xbe 0x175>;
+ };
+ ir_key2{
+ rockchip,usercode = <0xff00>;
+ rockchip,key_table =
+ <0xf9 KEY_HOME>,
+ <0xbf KEY_BACK>,
+ <0xfb KEY_MENU>,
+ <0xaa KEY_REPLY>,
+ <0xb9 KEY_UP>,
+ <0xe9 KEY_DOWN>,
+ <0xb8 KEY_LEFT>,
+ <0xea KEY_RIGHT>,
+ <0xeb KEY_VOLUMEDOWN>,
+ <0xef KEY_VOLUMEUP>,
+ <0xf7 KEY_MUTE>,
+ <0xe7 KEY_POWER>,
+ <0xfc KEY_POWER>,
+ <0xa9 KEY_VOLUMEDOWN>,
+ <0xa8 KEY_VOLUMEDOWN>,
+ <0xe0 KEY_VOLUMEDOWN>,
+ <0xa5 KEY_VOLUMEDOWN>,
+ <0xab 183>,
+ <0xb7 388>,
+ <0xf8 184>,
+ <0xaf 185>,
+ <0xed KEY_VOLUMEDOWN>,
+ <0xee 186>,
+ <0xb3 KEY_VOLUMEDOWN>,
+ <0xf1 KEY_VOLUMEDOWN>,
+ <0xf2 KEY_VOLUMEDOWN>,
+ <0xf3 KEY_SEARCH>,
+ <0xb4 KEY_VOLUMEDOWN>,
+ <0xbe KEY_SEARCH>;
+ };
+ ir_key3{
+ rockchip,usercode = <0x1dcc>;
+ rockchip,key_table =
+ <0xee KEY_REPLY>,
+ <0xf0 KEY_BACK>,
+ <0xf8 KEY_UP>,
+ <0xbb KEY_DOWN>,
+ <0xef KEY_LEFT>,
+ <0xed KEY_RIGHT>,
+ <0xfc KEY_HOME>,
+ <0xf1 KEY_VOLUMEUP>,
+ <0xfd KEY_VOLUMEDOWN>,
+ <0xb7 KEY_SEARCH>,
+ <0xff KEY_POWER>,
+ <0xf3 KEY_MUTE>,
+ <0xbf KEY_MENU>,
+ <0xf9 0x191>,
+ <0xf5 0x192>,
+ <0xb3 388>,
+ <0xbe KEY_1>,
+ <0xba KEY_2>,
+ <0xb2 KEY_3>,
+ <0xbd KEY_4>,
+ <0xf9 KEY_5>,
+ <0xb1 KEY_6>,
+ <0xfc KEY_7>,
+ <0xf8 KEY_8>,
+ <0xb0 KEY_9>,
+ <0xb6 KEY_0>,
+ <0xb5 KEY_BACKSPACE>;
+ };
+};
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
+ lcdc = &lcdc;
spi0 = &spi0;
};
>;
temp-limit-enable = <1>;
target-temp = <85>;
+ status = "okay";
};
};
};
};
-
- adc-battery {
- compatible = "rk30-adc-battery";
- io-channels = <&adc 0>;
- dc_det_gpio = <&gpio2 GPIO_B1 GPIO_ACTIVE_LOW>;
- //bat_low_gpio = <&gpio0 GPIO_A7 GPIO_ACTIVE_LOW>;
- //chg_ok_gpio = <&gpio0 GPIO_B1 GPIO_ACTIVE_HIGH>;
- bat_table = <0 0 0 0 100 100
+ adc-battery {
+ compatible = "rk30-adc-battery";
+ io-channels = <&adc 0>, <&adc 3>;
+ dc_det_gpio = <&gpio2 GPIO_B1 GPIO_ACTIVE_LOW>;
+ auto_calibration = <0>;
+ ref_voltage = <3300>;
+ //bat_low_gpio = <&gpio0 GPIO_A7 GPIO_ACTIVE_LOW>;
+ //chg_ok_gpio = <&gpio0 GPIO_B1 GPIO_ACTIVE_HIGH>;
+ bat_table = <0 0 0 0 100 100
3500 3619 3678 3734 3742 3783 3813 3884 3968 4110 4220
3750 3710 3770 3830 3850 3880 3910 3980 4060 4240 4300
>;
- is_dc_charge = <1>;
- is_usb_charge = <0>;
-
- };
+ is_dc_charge = <1>;
+ is_usb_charge = <0>;
+ };
};
&rk3126_cif_sensor{
status = "okay";
};
+
+&gmac {
+ status = "disabled";
+};
};
- gc0309{
+ gc0329{
is_front = <0>;
//rockchip,power = <&gpio2 GPIO_B2 GPIO_ACTIVE_HIGH>;
//rockchip,power_pmu_name1 = "rk818_ldo4";
rockchip,powerdown = <&gpio3 GPIO_B3 GPIO_ACTIVE_HIGH>;
//rockchip,powerdown_pmu = "";
//rockchip,powerdown_pmu_voltage = <3000000>;
- pwdn_active = <gc0309_PWRDN_ACTIVE>;
+ pwdn_active = <gc0329_PWRDN_ACTIVE>;
pwr_active = <PWR_ACTIVE_HIGH>;
mir = <0>;
- flash_attach = <0>;
- resolution = <gc0309_FULL_RESOLUTION>;
- powerup_sequence = <gc0309_PWRSEQ>;
+ flash_attach = <1>;
+ //rockchip,flash = <>;
+ flash_active = <1>;
+ resolution = <gc0329_FULL_RESOLUTION>;
+ powerup_sequence = <gc0329_PWRSEQ>;
orientation = <0>;
- i2c_add = <gc0309_I2C_ADDR>;
+ i2c_add = <gc0329_I2C_ADDR>;
i2c_rata = <100000>;
i2c_chl = <1>;
cif_chl = <0>;
};
};
&sdmmc {
- cd-gpios = <&gpio2 GPIO_A3 GPIO_ACTIVE_HIGH>;/*CD GPIO*/
+ cd-gpios = <&gpio2 GPIO_A7 GPIO_ACTIVE_HIGH>;/*CD GPIO*/
};
&codec {
&clk_core_dvfs_table {
operating-points = <
/* KHz uV */
- 216000 975000
- 408000 975000
- 600000 1075000
- 696000 1100000
- 816000 1150000
- 1008000 1300000
- 1200000 1375000
+ 216000 950000
+ 408000 950000
+ 600000 1050000
+ 696000 1050000
+ 816000 1125000
+ 1008000 1275000
+ 1200000 1400000
>;
+ virt-temp-limit-1-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 1008000
+ 85 1200000
+ 95 1200000
+ 100 1200000
+ >;
+ virt-temp-limit-2-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 912000
+ 85 1008000
+ 95 1104000
+ 100 1200000
+ >;
+ virt-temp-limit-3-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 816000
+ 85 912000
+ 95 100800
+ 100 110400
+ >;
+ virt-temp-limit-4-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 816000
+ 85 912000
+ 95 100800
+ 100 110400
+ >;
+ temp-limit-enable = <1>;
+ target-temp = <85>;
status="okay";
};
/* KHz uV */
200000 950000
300000 950000
- 400000 1000000
+ 400000 1025000
533000 1225000
>;
1296000 1350000
1320000 1375000
>;
+ virt-temp-limit-1-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 1008000
+ 85 1200000
+ 95 1200000
+ 100 1200000
+ >;
+ virt-temp-limit-2-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 912000
+ 85 1008000
+ 95 1104000
+ 100 1200000
+ >;
+ virt-temp-limit-3-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 816000
+ 85 912000
+ 95 100800
+ 100 110400
+ >;
+ virt-temp-limit-4-cpu-busy = <
+ /* target-temp limit-freq */
+ 75 816000
+ 85 912000
+ 95 100800
+ 100 110400
+ >;
+ temp-limit-enable = <1>;
+ target-temp = <85>;
status="okay";
};
#clock-cells = <0>;
rockchip,clkops-idx =
<CLKOPS_RATE_MUX_DIV>;
- rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
};
clk_cif_out: clk_cif_out_mux {
0 3
>;
regu-mode-en = <0>;
+ lkg_adjust_volt_en = <1>;
+ channel = <0>;
+ def_table_lkg = <35>;
+ min_adjust_freq = <1200000>;
+ lkg_adjust_volt_table = <
+ /*lkg(mA) volt(uV)*/
+ 60 25000
+ >;
};
};
};
hclk_vio: hclk_vio_div {
compatible = "rockchip,rk3188-div-con";
rockchip,bits = <8 5>;
- clocks = <&aclk_vio0>;
+ clocks = <&clk_gates15 11>;
clock-output-names = "hclk_vio";
rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
#clock-cells = <0>;
reg = <0x019c 0x4>;
clocks =
<&aclk_rga>, <&hclk_vio>,
- <&aclk_vio0>, <&hclk_vio>,
+ <&clk_gates15 11>, <&hclk_vio>,
- <&dummy>, <&aclk_vio0>,
- <&hclk_vio>, <&aclk_vio1>,
+ <&dummy>, <&clk_gates15 11>,
+ <&hclk_vio>, <&clk_gates15 12>,
- <&hclk_vio>, <&hclk_vio>,
- <&hclk_vio>, <&aclk_vio0>,
+ <&hclk_vio>, <&dummy>,
+ <&dummy>, <&aclk_vio0>,
<&aclk_vio1>, <&aclk_rga>,
- <&aclk_vio0>, <&hclk_vio>;
+ <&clk_gates15 11>, <&hclk_vio>;
clock-output-names =
- "reserved", /*"g_aclk_rga",*/ "g_hclk_rga",
+ "reserved", /*"g_aclk_rga"*/ "g_hclk_rga",
"g_aclk_iep", "g_hclk_iep",
"g_aclk_lcdc_iep", "g_aclk_lcdc0",
"g_hclk_lcdc0", "g_aclk_lcdc1",
- "g_hclk_lcdc1", "g_h_vio_ahb",
- "g_hclk_vio_niu", "g_aclk_vio0_niu",
+ "g_hclk_lcdc1", "reserved", /* "g_h_vio_ahb" */
+ "reserved",/*"g_hclk_vio_niu"*/ "g_aclk_vio0_niu",
- "g_aclk_vio1_niu", "reserved",/*"g_aclk_rga_niu",*/
+ "g_aclk_vio1_niu", "reserved",/*"g_aclk_rga_niu"*/
"g_aclk_vip", "g_hclk_vip";
rockchip,suspend-clkgating-setting=<0x0 0x0>;
reg = <0x01a0 0x4>;
clocks =
<&pclkin_cif>, <&hclk_vio>,
- <&aclk_vio1>, <&pclkin_isp>,
+ <&clk_gates15 12>, <&pclkin_isp>,
<&hclk_vio>, <&hclk_vio>,
<&hclk_vio>, <&hclk_vio>,
<&hclk_vio>, <&hclk_vio>,
- <&hclk_vio>, <&hclk_vio>,
+ <&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>;
"g_p_mipi_csi", "g_pclk_lvds_phy",
"g_pclk_edp_ctrl", "g_p_hdmi_ctrl",
- "g_hclk_vio2_h2p", "g_pclk_vio2_h2p",
+ "reserved", "reserved", /* bit10:"g_hclk_vio2_h2p" bit11: "g_pclk_vio2_h2p" */
"reserved", "reserved",
"reserved", "reserved";
power-gpio = <&gpio0 GPIO_A6 GPIO_ACTIVE_HIGH>;
// power-pmu = "act_ldo"
reset-gpio = <&gpio4 GPIO_A7 GPIO_ACTIVE_LOW>;
+ status = "disabled"; //if want to use gmac, please set "okay"
};
&pinctrl {
BT,power_gpio = <&gpio4 GPIO_D3 GPIO_ACTIVE_HIGH>;
BT,reset_gpio = <&gpio4 GPIO_D5 GPIO_ACTIVE_HIGH>;
BT,wake_gpio = <&gpio4 GPIO_D2 GPIO_ACTIVE_HIGH>;
- BT,wake_host_irq = <&gpio4 GPIO_D7 GPIO_ACTIVE_LOW>;
+ BT,wake_host_irq = <&gpio4 GPIO_D7 GPIO_ACTIVE_HIGH>;
status = "okay";
};
clock_in_out = "input";
tx_delay = <0x28>;
rx_delay = <0x10>;
+ status = "disabled"; //if want to use gmac, please set "okay"
};
&pinctrl {
};
&spi0 {
- status = "okay";
+ status = "disabled";
max-freq = <48000000>;
/*
spi_test@00 {
};
&spi1 {
- status = "okay";
+ status = "disabled";
max-freq = <48000000>;
/*
spi_test@10 {
};
&spi2 {
- status = "okay";
+ status = "disabled";
max-freq = <48000000>;
/*
spi_test@20 {
rockchip,cabc_mode = <0>;
power_ctr: power_ctr {
rockchip,debug = <0>;
+ /*lcd_18:lcd18 {
+ rockchip,power_type = <REGULATOR>;
+ rockchip,regulator_name = "vcc_18";
+ rockchip,regulator_voltage = <1800000>;
+ rockchip,delay = <5>;
+ };*/
+
lcd_en:lcd_en {
rockchip,power_type = <GPIO>;
gpios = <&gpio7 GPIO_A3 GPIO_ACTIVE_HIGH>;
// 1704000 1350000
// 1800000 1400000
>;
+ support-pvtm = <1>;
+ pvtm-operating-points = <
+ /* KHz uV margin(uV)*/
+ 126000 900000 25000
+ 216000 900000 25000
+ 312000 900000 25000
+ 408000 900000 25000
+ 600000 900000 25000
+ 696000 950000 25000
+ 816000 1000000 25000
+ 1008000 1050000 25000
+ 1200000 1100000 25000
+ 1416000 1200000 25000
+ 1512000 1300000 25000
+ 1608000 1350000 25000
+ >;
status="okay";
};
clocks-enable {
compatible = "rockchip,clocks-enable";
clocks =
+ /*PLL*/
+ <&clk_dpll>, <&clk_gpll>,
+
/*PD_CORE*/
<&clk_gates0 2>, <&clk_core0>,
<&clk_core1>, <&clk_core2>,
/*PD_BUS*/
<&aclk_bus>, <&clk_gates0 3>,
<&hclk_bus>, <&pclk_bus>,
- <&clk_gates13 8>, <&clk_crypto>,
+ <&clk_gates13 8>,
<&clk_gates0 7>,
/*TIMER*/
<&clk_gates10 12>,/*aclk_dma1*/
<&clk_gates10 13>,/*aclk_strc_sys*/
<&clk_gates10 4>,/*aclk_intmem*/
- <&clk_gates11 6>,/*aclk_crypto*/
- <&clk_gates11 8>,/*aclk_ccp*/
/*hclk_bus*/
- <&clk_gates11 7>,/*hclk_crypto*/
<&clk_gates10 9>,/*hclk_rom*/
/*pclk_bus*/
<&clk_gates17 2>,/*pclk_pmu_niu*/
<&clk_gates17 3>,/*pclk_sgrf*/
- /*hclk_vio*/
- <&clk_gates15 9>,/*hclk_vio_ahb_arbi*/
- <&clk_gates15 10>,/*hclk_vio_niu*/
- <&clk_gates16 10>,/*hclk_vio2_h2p*/
- <&clk_gates16 11>,/*pclk_vio2_h2p*/
-
- /*aclk_vio0*/
- <&clk_gates15 11>,/*aclk_vio0_niu*/
-
- /*aclk_vio1*/
- <&clk_gates15 12>,/*aclk_vio1_niu*/
-
- /*HDMI*/
- //<&clk_gates5 12>,/*hdmi_hdcp_clk*/
-
/*UART*/
<&clk_gates11 9>,/*pclk_uart2*/
pinctrl-0 = <&i2c1_sda &i2c1_scl>;
pinctrl-1 = <&i2c1_gpio>;
gpios = <&gpio8 GPIO_A4 GPIO_ACTIVE_LOW>, <&gpio8 GPIO_A5 GPIO_ACTIVE_LOW>;
- clocks = <&clk_gates10 3>;
+ clocks = <&clk_gates6 13>;
rockchip,check-idle = <1>;
status = "disabled";
};
pinctrl-0 = <&i2c2_sda &i2c2_scl>;
pinctrl-1 = <&i2c2_gpio>;
gpios = <&gpio6 GPIO_B1 GPIO_ACTIVE_LOW>, <&gpio6 GPIO_B2 GPIO_ACTIVE_LOW>;
- clocks = <&clk_gates6 13>;
+ clocks = <&clk_gates10 3>;
rockchip,check-idle = <1>;
status = "disabled";
};
816000 1100000
1008000 1100000
>;
+ channel = <0>;
temp-limit-enable = <1>;
target-temp = <80>;
- temp-channel = <1>;
normal-temp-limit = <
/*delta-temp delta-freq*/
3 96000
300000 1200000
400000 1200000
>;
+ channel = <2>;
status = "disabled";
};
};
300000 1200000
400000 1200000
>;
+ channel = <1>;
status = "okay";
regu-mode-table = <
/*freq mode*/
CONFIG_IPV6_SUBTREES=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_ROCKCHIP_PWM_REGULATOR=y
-CONFIG_MALI400=y
+CONFIG_MALI400=m
# CONFIG_MALI400_PROFILING is not set
CONFIG_MALI_SHARED_INTERRUPTS=y
CONFIG_FB=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_ROCKCHIP=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_BACKLIGHT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HYM8563=y
-CONFIG_RK808_RTC=y
CONFIG_STAGING=y
CONFIG_ZSMALLOC=y
CONFIG_ZRAM=y
CONFIG_MEDIA_RC_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_CAMSYS_DRV=y
+CONFIG_FLASHLIGHT=y
+CONFIG_LEDS_RT8547=y
+# CONFIG_RK30_CAMERA_ONEFRAME is not set
CONFIG_MALI_MIDGARD=m
CONFIG_MALI_MIDGARD_DVFS=y
CONFIG_MALI_MIDGARD_RT_PM=y
else
type = "";
+ if (rockchip_get_cpu_version())
+ return sprintf(buf, "%sv%lu\n", type,
+ rockchip_get_cpu_version());
+
return sprintf(buf, "%s\n", type);
}
#include <linux/tick.h>
#include <dt-bindings/clock/rk_system_status.h>
#include "../../../drivers/clk/rockchip/clk-pd.h"
+#include "efuse.h"
extern int rockchip_tsadc_get_temp(int chn);
}
#endif
+static struct cpufreq_frequency_table rk3288v0_arm_pvtm_table[] = {
+ {.frequency = 216000, .index = 4006},
+ {.frequency = 408000, .index = 6518},
+ {.frequency = 600000, .index = 8345},
+ {.frequency = 816000, .index = 11026},
+ {.frequency = 1008000, .index = 12906},
+ {.frequency = 1200000, .index = 15532},
+ {.frequency = 1416000, .index = 18076},
+ {.frequency = 1608000, .index = 21282},
+ {.frequency = CPUFREQ_TABLE_END, .index = 1},
+};
+
+static struct pvtm_info rk3288v0_arm_pvtm_info = {
+ .compatible = "rockchip,rk3288",
+ .pvtm_table = rk3288v0_arm_pvtm_table,
+ .channel = ARM_DVFS_CH,
+ .process_version = RK3288_PROCESS_V0,
+ .scan_rate_hz = 216000000,
+ .sample_time_us = 1000,
+ .volt_step_uv = 12500,
+ .delta_pvtm_by_volt = 400,
+ .delta_pvtm_by_temp = 14,
+ .volt_margin_uv = 25000,
+ .min_volt_uv = 850000,
+ .max_volt_uv = 1400000,
+};
+
+static struct cpufreq_frequency_table rk3288v1_arm_pvtm_table[] = {
+ {.frequency = 216000, .index = 4710},
+ {.frequency = 408000, .index = 7200},
+ {.frequency = 600000, .index = 9192},
+ {.frequency = 816000, .index = 12560},
+ {.frequency = 1008000, .index = 14741},
+ {.frequency = 1200000, .index = 16886},
+ {.frequency = 1416000, .index = 20081},
+ {.frequency = 1608000, .index = 24061},
+ {.frequency = CPUFREQ_TABLE_END, .index = 1},
+};
+
+static struct pvtm_info rk3288v1_arm_pvtm_info = {
+ .compatible = "rockchip,rk3288",
+ .pvtm_table = rk3288v1_arm_pvtm_table,
+ .channel = ARM_DVFS_CH,
+ .process_version = RK3288_PROCESS_V1,
+ .scan_rate_hz = 216000000,
+ .sample_time_us = 1000,
+ .volt_step_uv = 12500,
+ .delta_pvtm_by_volt = 450,
+ .delta_pvtm_by_temp = 7,
+ .volt_margin_uv = 25000,
+ .min_volt_uv = 850000,
+ .max_volt_uv = 1400000,
+};
+
+static struct pvtm_info *pvtm_info_table[] = {
+ &rk3288v0_arm_pvtm_info,
+ &rk3288v1_arm_pvtm_info
+};
+
+static int pvtm_set_single_dvfs(struct dvfs_node *dvfs_node, u32 idx,
+ struct pvtm_info *info, int *pvtm_list,
+ u32 min_pvtm)
+{
+ struct cpufreq_frequency_table *dvfs_table = dvfs_node->dvfs_table;
+ struct cpufreq_frequency_table *pvtm_table = dvfs_node->pvtm_table;
+ int target_pvtm, pvtm_margin, volt_margin;
+ unsigned int n_voltages = dvfs_node->vd->n_voltages;
+ int *volt_list = dvfs_node->vd->volt_list;
+ int n, temp;
+
+ volt_margin = info->volt_margin_uv + pvtm_table[idx].index;
+ n = volt_margin/info->volt_step_uv;
+ if (volt_margin%info->volt_step_uv)
+ n++;
+
+ pvtm_margin = n*info->delta_pvtm_by_volt;
+ temp = rockchip_tsadc_get_temp(1);
+ target_pvtm = min_pvtm+temp * info->delta_pvtm_by_temp + pvtm_margin;
+
+ DVFS_DBG("=====%s: temp:%d, freq:%d, target pvtm:%d=====\n",
+ __func__, temp, dvfs_table[idx].frequency, target_pvtm);
+
+ for (n = 0; n < n_voltages; n++) {
+ if (pvtm_list[n] >= target_pvtm) {
+ dvfs_table[idx].index = volt_list[n];
+ DVFS_DBG("freq[%d]=%d, volt=%d\n",
+ idx, dvfs_table[idx].frequency, volt_list[n]);
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+
+ return 0;
+}
+
+static void pvtm_set_dvfs_table(struct dvfs_node *dvfs_node)
+{
+ struct cpufreq_frequency_table *dvfs_table = dvfs_node->dvfs_table;
+ struct pvtm_info *info = dvfs_node->pvtm_info;
+ struct regulator *regulator = dvfs_node->vd->regulator;
+ int i, j;
+ int ret = 0;
+ int pvtm_list[VD_VOL_LIST_CNT] = {0};
+ unsigned int n_voltages = dvfs_node->vd->n_voltages;
+ int *volt_list = dvfs_node->vd->volt_list;
+
+ if (!info)
+ return;
+
+ clk_set_rate(dvfs_node->clk, info->scan_rate_hz);
+ DVFS_DBG("%s:%lu\n", __func__, clk_get_rate(dvfs_node->clk));
+
+ for (i = 0; i < n_voltages; i++) {
+ if ((volt_list[i] >= info->min_volt_uv) &&
+ (volt_list[i] <= info->max_volt_uv)) {
+ regulator_set_voltage(regulator, volt_list[i],
+ volt_list[i]);
+ pvtm_list[i] = pvtm_get_value(info->channel,
+ info->sample_time_us);
+ }
+ }
+
+ for (i = 0; dvfs_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ for (j = 0; info->pvtm_table[j].frequency !=
+ CPUFREQ_TABLE_END; j++)
+ if (info->pvtm_table[j].frequency >=
+ dvfs_table[i].frequency) {
+ int min_pvtm = info->pvtm_table[j].index;
+
+ ret = pvtm_set_single_dvfs(dvfs_node,
+ i,
+ info,
+ pvtm_list,
+ min_pvtm);
+ break;
+ }
+
+ if (ret) {
+ DVFS_WARNING("freq: %d can not reach target pvtm\n",
+ dvfs_table[i].frequency);
+ break;
+ }
+
+ if (info->pvtm_table[j].frequency == CPUFREQ_TABLE_END) {
+ DVFS_WARNING("not support freq :%d, max freq is %d\n",
+ dvfs_table[i].frequency,
+ info->pvtm_table[j-1].frequency);
+ break;
+ }
+ }
+}
+
static void dvfs_virt_temp_limit_work_func(void)
{
const struct cpufreq_frequency_table *limits_table = NULL;
}
static DECLARE_DELAYED_WORK(dvfs_temp_limit_work, dvfs_temp_limit_work_func);
-
int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate, unsigned int max_rate)
{
u32 rate = 0, ret = 0;
}
EXPORT_SYMBOL(dvfs_set_freq_volt_table);
+static int get_adjust_volt_by_leakage(struct dvfs_node *dvfs_node)
+{
+ int leakage = 0;
+ int delta_leakage = 0;
+ int i = 0;
+ int adjust_volt = 0;
+
+ if (!dvfs_node->vd)
+ return 0;
+
+ if (dvfs_node->lkg_info.def_table_lkg == -1)
+ return 0;
+
+ leakage = rockchip_get_leakage(dvfs_node->channel);
+ if (!leakage || (leakage == 0xff))
+ return 0;
+
+ delta_leakage = leakage - dvfs_node->lkg_info.def_table_lkg;
+ if (delta_leakage <= 0) {
+ for (i = 0; (dvfs_node->lkg_info.table[i].dlt_volt !=
+ CPUFREQ_TABLE_END); i++) {
+ if (leakage > dvfs_node->lkg_info.table[i].lkg) {
+ adjust_volt =
+ dvfs_node->lkg_info.table[i].dlt_volt;
+ } else {
+ return adjust_volt;
+ }
+ }
+ } else if (delta_leakage > 0) {
+ for (i = 0; (dvfs_node->lkg_info.table[i].dlt_volt !=
+ CPUFREQ_TABLE_END); i++) {
+ if (leakage <= dvfs_node->lkg_info.table[i].lkg) {
+ adjust_volt =
+ -dvfs_node->lkg_info.table[i].dlt_volt;
+ return adjust_volt;
+ }
+ }
+ }
+ return adjust_volt;
+}
+
+static void adjust_table_by_leakage(struct dvfs_node *dvfs_node)
+{
+ int i, adjust_volt = get_adjust_volt_by_leakage(dvfs_node);
+
+ if (!adjust_volt)
+ return;
+
+ if (!dvfs_node->dvfs_table)
+ return;
+
+ if (dvfs_node->lkg_info.min_adjust_freq == -1)
+ return;
+
+ for (i = 0;
+ (dvfs_node->dvfs_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ if (dvfs_node->dvfs_table[i].frequency >=
+ dvfs_node->lkg_info.min_adjust_freq)
+ dvfs_node->dvfs_table[i].index += adjust_volt;
+ }
+}
+
int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node)
{
struct cpufreq_frequency_table clk_fv;
unsigned int mode;
int ret;
-
if (!clk_dvfs_node)
return -EINVAL;
dvfs_table_round_clk_rate(clk_dvfs_node);
dvfs_get_rate_range(clk_dvfs_node);
clk_dvfs_node->freq_limit_en = 1;
+ if (clk_dvfs_node->lkg_adjust_volt_en)
+ adjust_table_by_leakage(clk_dvfs_node);
+ if (clk_dvfs_node->support_pvtm)
+ pvtm_set_dvfs_table(clk_dvfs_node);
dvfs_table_round_volt(clk_dvfs_node);
clk_dvfs_node->set_freq = clk_dvfs_node_get_rate_kz(clk_dvfs_node->clk);
clk_dvfs_node->last_set_rate = clk_dvfs_node->set_freq*1000;
}
EXPORT_SYMBOL_GPL(rk_regist_clk);
-static int rk_convert_cpufreq_table(struct dvfs_node *dvfs_node)
-{
- struct opp *opp;
- struct device *dev;
- struct cpufreq_frequency_table *table;
- int i;
-
- table = dvfs_node->dvfs_table;
- dev = &dvfs_node->dev;
-
- for (i = 0; table[i].frequency!= CPUFREQ_TABLE_END; i++){
- opp = opp_find_freq_exact(dev, table[i].frequency * 1000, true);
- if (IS_ERR(opp))
- return PTR_ERR(opp);
- table[i].index = opp_get_voltage(opp);
- }
- return 0;
-}
-
static struct cpufreq_frequency_table *of_get_temp_limit_table(struct device_node *dev_node, const char *propname)
{
struct cpufreq_frequency_table *temp_limt_table = NULL;
}
+static int of_get_dvfs_table(struct device_node *dev_node,
+ struct cpufreq_frequency_table **dvfs_table)
+{
+ struct cpufreq_frequency_table *tmp_dvfs_table = NULL;
+ const struct property *prop;
+ const __be32 *val;
+ int nr, i;
+
+ prop = of_find_property(dev_node, "operating-points", NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -EINVAL;
+
+ nr = prop->length / sizeof(u32);
+ if (nr % 2) {
+ pr_err("%s: Invalid freq list\n", __func__);
+ return -EINVAL;
+ }
+
+ tmp_dvfs_table = kzalloc(sizeof(*tmp_dvfs_table) *
+ (nr/2 + 1), GFP_KERNEL);
+ val = prop->value;
+
+ for (i = 0; i < nr/2; i++) {
+ tmp_dvfs_table[i].frequency = be32_to_cpup(val++);
+ tmp_dvfs_table[i].index = be32_to_cpup(val++);
+ }
+
+ tmp_dvfs_table[i].index = 0;
+ tmp_dvfs_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *dvfs_table = tmp_dvfs_table;
+
+ return 0;
+}
+
+
+static int of_get_dvfs_pvtm_table(struct device_node *dev_node,
+ struct cpufreq_frequency_table **dvfs_table,
+ struct cpufreq_frequency_table **pvtm_table)
+{
+ struct cpufreq_frequency_table *tmp_dvfs_table = NULL;
+ struct cpufreq_frequency_table *tmp_pvtm_table = NULL;
+ const struct property *prop;
+ const __be32 *val;
+ int nr, i;
+
+ prop = of_find_property(dev_node, "pvtm-operating-points", NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -EINVAL;
+
+ nr = prop->length / sizeof(u32);
+ if (nr % 3) {
+ pr_err("%s: Invalid freq list\n", __func__);
+ return -EINVAL;
+ }
+
+ tmp_dvfs_table = kzalloc(sizeof(*tmp_dvfs_table) *
+ (nr/3 + 1), GFP_KERNEL);
+
+ tmp_pvtm_table = kzalloc(sizeof(*tmp_pvtm_table) *
+ (nr/3 + 1), GFP_KERNEL);
+
+ val = prop->value;
+
+ for (i = 0; i < nr/3; i++) {
+ tmp_dvfs_table[i].frequency = be32_to_cpup(val++);
+ tmp_dvfs_table[i].index = be32_to_cpup(val++);
+
+ tmp_pvtm_table[i].frequency = tmp_dvfs_table[i].frequency;
+ tmp_pvtm_table[i].index = be32_to_cpup(val++);
+ }
+
+ tmp_dvfs_table[i].index = 0;
+ tmp_dvfs_table[i].frequency = CPUFREQ_TABLE_END;
+
+ tmp_pvtm_table[i].index = 0;
+ tmp_pvtm_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *dvfs_table = tmp_dvfs_table;
+ *pvtm_table = tmp_pvtm_table;
+
+ return 0;
+}
+
+static struct lkg_adjust_volt_table
+ *of_get_lkg_adjust_volt_table(struct device_node *np,
+ const char *propname)
+{
+ struct lkg_adjust_volt_table *lkg_adjust_volt_table = NULL;
+ const struct property *prop;
+ const __be32 *val;
+ int nr, i;
+
+ prop = of_find_property(np, propname, NULL);
+ if (!prop)
+ return NULL;
+ if (!prop->value)
+ return NULL;
+
+ nr = prop->length / sizeof(s32);
+ if (nr % 2) {
+ pr_err("%s: Invalid freq list\n", __func__);
+ return NULL;
+ }
+
+ lkg_adjust_volt_table =
+ kzalloc(sizeof(struct lkg_adjust_volt_table) *
+ (nr/2 + 1), GFP_KERNEL);
+
+ val = prop->value;
+
+ for (i = 0; i < nr/2; i++) {
+ lkg_adjust_volt_table[i].lkg = be32_to_cpup(val++);
+ lkg_adjust_volt_table[i].dlt_volt = be32_to_cpup(val++);
+ }
+
+ lkg_adjust_volt_table[i].lkg = 0;
+ lkg_adjust_volt_table[i].dlt_volt = CPUFREQ_TABLE_END;
+
+ return lkg_adjust_volt_table;
+}
+
+static int dvfs_node_parse_dt(struct device_node *np,
+ struct dvfs_node *dvfs_node)
+{
+ int process_version = rockchip_process_version();
+ int i = 0;
+ int ret;
+
+ of_property_read_u32_index(np, "channel", 0, &dvfs_node->channel);
+
+ pr_info("channel:%d, lkg:%d\n",
+ dvfs_node->channel, rockchip_get_leakage(dvfs_node->channel));
+
+ of_property_read_u32_index(np, "regu-mode-en", 0,
+ &dvfs_node->regu_mode_en);
+ if (dvfs_node->regu_mode_en)
+ dvfs_node->regu_mode_table = of_get_regu_mode_table(np);
+ else
+ dvfs_node->regu_mode_table = NULL;
+
+ of_property_read_u32_index(np, "temp-limit-enable", 0,
+ &temp_limit_enable);
+ if (temp_limit_enable) {
+ of_property_read_u32_index(np, "target-temp", 0, &target_temp);
+ pr_info("target-temp:%d\n", target_temp);
+ dvfs_node->nor_temp_limit_table =
+ of_get_temp_limit_table(np,
+ "normal-temp-limit");
+ dvfs_node->per_temp_limit_table =
+ of_get_temp_limit_table(np,
+ "performance-temp-limit");
+ dvfs_node->virt_temp_limit_table[0] =
+ of_get_temp_limit_table(np,
+ "virt-temp-limit-1-cpu-busy");
+ dvfs_node->virt_temp_limit_table[1] =
+ of_get_temp_limit_table(np,
+ "virt-temp-limit-2-cpu-busy");
+ dvfs_node->virt_temp_limit_table[2] =
+ of_get_temp_limit_table(np,
+ "virt-temp-limit-3-cpu-busy");
+ dvfs_node->virt_temp_limit_table[3] =
+ of_get_temp_limit_table(np,
+ "virt-temp-limit-4-cpu-busy");
+ }
+ dvfs_node->temp_limit_rate = -1;
+
+ ret = of_property_read_u32_index(np, "support-pvtm", 0,
+ &dvfs_node->support_pvtm);
+ if (!ret) {
+ if (of_get_dvfs_pvtm_table(np, &dvfs_node->dvfs_table,
+ &dvfs_node->pvtm_table))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(pvtm_info_table); i++) {
+ struct pvtm_info *pvtm_info = pvtm_info_table[i];
+
+ if ((pvtm_info->channel == dvfs_node->channel) &&
+ (pvtm_info->process_version == process_version) &&
+ of_machine_is_compatible(pvtm_info->compatible)) {
+ dvfs_node->pvtm_info = pvtm_info;
+ break;
+ }
+ }
+
+ if (!dvfs_node->pvtm_info)
+ dvfs_node->support_pvtm = 0;
+ } else {
+ if (of_get_dvfs_table(np, &dvfs_node->dvfs_table))
+ return -EINVAL;
+ }
+
+ of_property_read_u32_index(np, "lkg_adjust_volt_en", 0,
+ &dvfs_node->lkg_adjust_volt_en);
+ if (dvfs_node->lkg_adjust_volt_en) {
+ dvfs_node->lkg_info.def_table_lkg = -1;
+ of_property_read_u32_index(np, "def_table_lkg", 0,
+ &dvfs_node->lkg_info.def_table_lkg);
+
+ dvfs_node->lkg_info.min_adjust_freq = -1;
+ of_property_read_u32_index(np, "min_adjust_freq", 0,
+ &dvfs_node->lkg_info.min_adjust_freq
+ );
+
+ dvfs_node->lkg_info.table =
+ of_get_lkg_adjust_volt_table(np,
+ "lkg_adjust_volt_table");
+ }
+
+ return 0;
+}
+
int of_dvfs_init(void)
{
struct vd_node *vd;
struct device_node *dvfs_dev_node, *clk_dev_node, *vd_dev_node, *pd_dev_node;
struct dvfs_node *dvfs_node;
struct clk *clk;
- const __be32 *val;
int ret;
DVFS_DBG("%s\n", __func__);
+ pr_info("process version: %d\n", rockchip_process_version());
dvfs_dev_node = of_find_node_by_name(NULL, "dvfs");
if (IS_ERR_OR_NULL(dvfs_dev_node)) {
dvfs_node->pd = pd;
dvfs_node->vd = vd;
- val = of_get_property(clk_dev_node, "regu-mode-en", NULL);
- if (val)
- dvfs_node->regu_mode_en = be32_to_cpup(val);
- if (dvfs_node->regu_mode_en)
- dvfs_node->regu_mode_table = of_get_regu_mode_table(clk_dev_node);
- else
- dvfs_node->regu_mode_table = NULL;
-
- val = of_get_property(clk_dev_node, "temp-limit-enable", NULL);
- if (val)
- temp_limit_enable = be32_to_cpup(val);
- if (temp_limit_enable) {
- val = of_get_property(clk_dev_node, "target-temp", NULL);
- if (val)
- target_temp = be32_to_cpup(val);
- val = of_get_property(clk_dev_node, "temp-channel", NULL);
- if (val)
- dvfs_node->temp_channel = be32_to_cpup(val);
-
- dvfs_node->nor_temp_limit_table = of_get_temp_limit_table(clk_dev_node, "normal-temp-limit");
- dvfs_node->per_temp_limit_table = of_get_temp_limit_table(clk_dev_node, "performance-temp-limit");
- dvfs_node->virt_temp_limit_table[0] =
- of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-1-cpu-busy");
- dvfs_node->virt_temp_limit_table[1] =
- of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-2-cpu-busy");
- dvfs_node->virt_temp_limit_table[2] =
- of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-3-cpu-busy");
- dvfs_node->virt_temp_limit_table[3] =
- of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-4-cpu-busy");
- }
- dvfs_node->temp_limit_rate = -1;
- dvfs_node->dev.of_node = clk_dev_node;
- ret = of_init_opp_table(&dvfs_node->dev);
- if (ret) {
- DVFS_ERR("%s:clk(%s) get opp table err:%d\n", __func__, dvfs_node->name, ret);
- kfree(dvfs_node);
- continue;
- }
-
- ret = opp_init_cpufreq_table(&dvfs_node->dev, &dvfs_node->dvfs_table);
- if (ret) {
- DVFS_ERR("%s:clk(%s) get cpufreq table err:%d\n", __func__, dvfs_node->name, ret);
- kfree(dvfs_node);
- continue;
- }
- ret = rk_convert_cpufreq_table(dvfs_node);
- if (ret) {
- kfree(dvfs_node);
+ if (dvfs_node_parse_dt(clk_dev_node, dvfs_node))
continue;
- }
clk = clk_get(NULL, clk_dev_node->name);
if (IS_ERR(clk)){
struct rockchip_efuse {
int (*get_leakage)(int ch);
int efuse_version;
+ int process_version;
};
static struct rockchip_efuse efuse;
return ret;
}
+static int __init rk3288_get_process_version(void)
+{
+ int ret = efuse_buf[6]&0x0f;
+
+ return ret;
+}
+
static int rk3288_get_leakage(int ch)
{
if ((ch < 0) || (ch > 2))
system_serial_high = crc32(system_serial_low, buf + 8, 8);
}
+int rk312x_efuse_readregs(u32 addr, u32 length, u8 *buf)
+{
+ int ret = length;
+
+ if (!length)
+ return 0;
+
+ efuse_writel(EFUSE_LOAD, REG_EFUSE_CTRL);
+ udelay(2);
+ do {
+ efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
+ (~(EFUSE_A_MASK << RK312X_EFUSE_A_SHIFT)),
+ REG_EFUSE_CTRL);
+ efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
+ ((addr & EFUSE_A_MASK) << RK312X_EFUSE_A_SHIFT),
+ REG_EFUSE_CTRL);
+ udelay(2);
+ efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
+ EFUSE_STROBE, REG_EFUSE_CTRL);
+ udelay(2);
+ *buf = efuse_readl(REG_EFUSE_DOUT);
+ efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
+ (~EFUSE_STROBE), REG_EFUSE_CTRL);
+ udelay(2);
+ buf++;
+ addr++;
+ } while (--length);
+ udelay(2);
+ efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
+ (~EFUSE_LOAD) , REG_EFUSE_CTRL);
+ udelay(1);
+
+ return ret;
+}
+
int rockchip_efuse_version(void)
{
return efuse.efuse_version;
}
+int rockchip_process_version(void)
+{
+ return efuse.process_version;
+}
+
int rockchip_get_leakage(int ch)
{
if (efuse.get_leakage)
if (ret == 32) {
efuse.get_leakage = rk3288_get_leakage;
efuse.efuse_version = rk3288_get_efuse_version();
+ efuse.process_version = rk3288_get_process_version();
rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
rk3288_set_system_serial();
} else {
pr_err("failed to read eFuse, return %d\n", ret);
}
+ } else if (cpu_is_rk312x()) {
+ ret = rk312x_efuse_readregs(0, 32, efuse_buf);
+ if (ret == 32)
+ efuse.get_leakage = rk3288_get_leakage;
+ else
+ pr_err("failed to read eFuse, return %d\n", ret);
}
}
/* eFuse controller register */
#define EFUSE_A_SHIFT (6)
+#define RK312X_EFUSE_A_SHIFT (7)
#define EFUSE_A_MASK (0x3FF)
//#define EFUSE_PD (1 << 5)
//#define EFUSE_PS (1 << 4)
#define GPU_LEAKAGE_CH 1
#define LOG_LEAKAGE_CH 2
+#define RK3288_PROCESS_V0 0
+#define RK3288_PROCESS_V1 1
+
int rockchip_efuse_version(void);
+int rockchip_process_version(void);
int rockchip_get_leakage(int ch);
#endif
//static void ddr_gpio_set_in_output(u8 port,u8 bank,u8 b_gpio,u8 type);
static void ddr_pin_set_fun(u8 port,u8 bank,u8 b_gpio,u8 fun);
-
/*************************cru define********************************************/
#define RK3288_PLL_BYPASS CRU_W_MSK_SETBITS(1,0,0x1)
#define RK3288_PLL_NO_BYPASS CRU_W_MSK_SETBITS(0,0,0x1)
-
/*******************************gpio define **********************************************/
/* GPIO control registers */
static u32 rkpm_slp_mode_set(u32 ctrbits)
{
u32 mode_set,mode_set1;
-
// setting gpio0_a0 arm off pin
sgrf_soc_con0=reg_readl(RK_SGRF_VIRT+RK3288_SGRF_SOC_CON0);
}
else if(rkpm_chk_val_ctrbits(ctrbits,RKPM_CTR_ARMDP_LPMD))
{
- rkpm_ddr_printascii("-armdp-");
- mode_set|=BIT(pmu_a12_0_pd_en);
+ rkpm_ddr_printascii("-armdp-");
+ mode_set |= BIT(pmu_a12_0_pd_en)
+ | BIT(pmu_sref0_enter_en) | BIT(pmu_sref1_enter_en)
+ | BIT(pmu_ddr0_gating_en) | BIT(pmu_ddr1_gating_en)
+ | BIT(pmu_chip_pd_en);
}
else if(rkpm_chk_val_ctrbits(ctrbits,RKPM_CTR_ARMOFF_LPMD))
{
rkpm_ddr_printascii("osc_off");
pmu_writel(32*30,RK3288_PMU_OSC_CNT);
pmu_writel(32*30,RK3288_PMU_STABL_CNT);
- }
- else
- {
- pmu_writel(24*1000*10,RK3288_PMU_STABL_CNT);
-
- // pmu_writel(24*1000*20,RK3288_PMU_CORE_PWRDWN_CNT);
- }
+ } else if (mode_set & BIT(pmu_a12_0_pd_en)) {
+ pmu_writel(0x0, RK3288_PMU_STABL_CNT);
+ pmu_writel(0x0, RK3288_PMU_OSC_CNT);
+ pmu_writel(0x0, RK3288_PMU_PLL_CNT);
+ pmu_writel(0x0, RK3288_PMU_DDR0IO_PWRON_CNT);
+ pmu_writel(0x0, RK3288_PMU_DDR1IO_PWRON_CNT);
+ pmu_writel(0x0, RK3288_PMU_GPU_PWRUP_CNT);
+ pmu_writel(0x0, RK3288_PMU_WAKEUP_RST_CLR_CNT);
+ /*pmu_writel(100,RK3288_PMU_CORE_PWRUP_CNT);*/
+ } else
+ pmu_writel(24*1000*10, RK3288_PMU_STABL_CNT);
if(mode_set&BIT(pmu_ddr0io_ret_en))
{
// rkpm_ddr_printhex(mode_set);
// rkpm_ddr_printhex(pmu_readl(RK3288_PMU_PWRMODE_CON));
-
+
return (pmu_readl(RK3288_PMU_PWRMODE_CON));
}
{
// u32 gpio_gate[2];
- if(power_mode&BIT(pmu_scu_en))
- {
- rkpm_gic_dist_save(&slp_gic_save[0]);
- }
+ if (power_mode & (BIT(pmu_scu_en) | BIT(pmu_a12_0_pd_en)))
+ rkpm_gic_dist_save(&slp_gic_save[0]);
#if 0
gpio_gate[0]=cru_readl(RK3288_CRU_GATEID_CONS(RK3288_CLKGATE_PCLK_GPIO0));
gpio_gate[1]=cru_readl(RK3288_CRU_GATEID_CONS(RK3288_CLKGATE_PCLK_GPIO1));
static inline void rkpm_peri_resume(u32 power_mode)
{
- if(power_mode&BIT(pmu_scu_en))
- {
- //fiq_glue_resume();
- rkpm_gic_dist_resume(&slp_gic_save[0]);
- fiq_glue_resume();
- //rkpm_ddr_printascii("gic res");
- }
+ if (power_mode & (BIT(pmu_scu_en) | BIT(pmu_a12_0_pd_en))) {
+ /*fiq_glue_resume();*/
+ rkpm_gic_dist_resume(&slp_gic_save[0]);
+ fiq_glue_resume();
+ /*rkpm_ddr_printascii("gic res");*/
+ }
if(power_mode&BIT(pmu_bus_pd_en))
{
slp_i2c_resume(0);// i2c pmu
static void gtclks_suspend(void)
{
- int i;
+ int i;
+
gpio7_pin_data1= gpio7_readl(0);
gpio7_pin_dir1 = gpio7_readl(0x04);
gpio7_pin_iomux1 = gpio7_readl(0x6c);
// rkpm_ddr_regs_dump(RK_CRU_VIRT,RK3288_CRU_CLKGATES_CON(0)
// ,RK3288_CRU_CLKGATES_CON(RK3288_CRU_CLKGATES_CON_CNT-1));
+
for(i=0;i<RK3288_CRU_CLKGATES_CON_CNT;i++)
{
clk_ungt_save[i]=cru_readl(RK3288_CRU_CLKGATES_CON(i));
//rkpm_ddr_regs_dump(RK_CRU_VIRT,RK3288_CRU_CLKGATES_CON(0)
// ,RK3288_CRU_CLKGATES_CON(RK3288_CRU_CLKGATES_CON_CNT-1));
grf_writel(0x00040004, 0x6c);
-
}
/********************************pll power down***************************************/
cru_writel(RK3288_PLL_PWR_DN, RK3288_PLL_CONS((pll_id), 3));
}
-static inline void plls_resume(u32 pll_id)
+static inline void plls_resume_pre(u32 pll_id)
{
- u32 pllcon0, pllcon1, pllcon2;
+ u32 pllcon0, pllcon1, pllcon2;
- if((plls_con3_save[pll_id]&RK3288_PLL_PWR_DN_MSK))
- return ;
-
- //enter slowmode
- cru_writel(RK3288_PLL_MODE_SLOW(pll_id), RK3288_CRU_MODE_CON);
-
- cru_writel(RK3288_PLL_PWR_ON, RK3288_PLL_CONS((pll_id),3));
- cru_writel(RK3288_PLL_NO_BYPASS, RK3288_PLL_CONS((pll_id),3));
-
- pllcon0 =plls_con0_save[pll_id];// cru_readl(RK3288_PLL_CONS((pll_id),0));
- pllcon1 = plls_con1_save[pll_id];//cru_readl(RK3288_PLL_CONS((pll_id),1));
- pllcon2 = plls_con2_save[pll_id];//cru_readl(RK3288_PLL_CONS((pll_id),2));
-
- //enter rest
- cru_writel(RK3288_PLL_RESET, RK3288_PLL_CONS(pll_id,3));
- cru_writel(pllcon0|CRU_W_MSK(0,0xf)|CRU_W_MSK(8,0x3f), RK3288_PLL_CONS(pll_id,0));
- cru_writel(pllcon1, RK3288_PLL_CONS(pll_id,1));
- cru_writel(pllcon2, RK3288_PLL_CONS(pll_id,2));
-
- pll_udelay(5);
- //udelay(5); //timer7 delay
+ cru_writel(RK3288_PLL_MODE_SLOW(pll_id), RK3288_CRU_MODE_CON);
- //return form rest
- cru_writel(RK3288_PLL_RESET_RESUME, RK3288_PLL_CONS(pll_id,3));
+ cru_writel(RK3288_PLL_PWR_ON, RK3288_PLL_CONS((pll_id), 3));
+ cru_writel(RK3288_PLL_NO_BYPASS, RK3288_PLL_CONS((pll_id), 3));
+
+ pllcon0 = plls_con0_save[pll_id];
+ pllcon1 = plls_con1_save[pll_id];
+ pllcon2 = plls_con2_save[pll_id];
+
+ /*enter rest*/
+ cru_writel(RK3288_PLL_RESET, RK3288_PLL_CONS(pll_id, 3));
+ cru_writel(pllcon0 | CRU_W_MSK(0, 0xf) | CRU_W_MSK(8, 0x3f)
+ , RK3288_PLL_CONS(pll_id, 0));
+ cru_writel(pllcon1, RK3288_PLL_CONS(pll_id, 1));
+ cru_writel(pllcon2, RK3288_PLL_CONS(pll_id, 2));
+}
+
+static inline void plls_resume(void)
+{
+ plls_resume_pre(APLL_ID);
+ plls_resume_pre(GPLL_ID);
+ plls_resume_pre(CPLL_ID);
+ plls_resume_pre(NPLL_ID);
+
+ pll_udelay(5);
+
+ /*return form rest*/
+ cru_writel(RK3288_PLL_RESET_RESUME, RK3288_PLL_CONS(APLL_ID, 3));
+ cru_writel(RK3288_PLL_RESET_RESUME, RK3288_PLL_CONS(GPLL_ID, 3));
+ cru_writel(RK3288_PLL_RESET_RESUME, RK3288_PLL_CONS(CPLL_ID, 3));
+ cru_writel(RK3288_PLL_RESET_RESUME, RK3288_PLL_CONS(NPLL_ID, 3));
+
+ /*wating lock state*/
+ pll_udelay(168);
+
+ pm_pll_wait_lock(APLL_ID);
+ pm_pll_wait_lock(GPLL_ID);
+ pm_pll_wait_lock(CPLL_ID);
+ pm_pll_wait_lock(NPLL_ID);
- //wating lock state
- pll_udelay(168);
- pm_pll_wait_lock(pll_id);
-
- cru_writel(plls_con3_save[pll_id]|(RK3288_PLL_BYPASS_MSK<<16),RK3288_PLL_CONS(pll_id,3));
+ cru_writel(plls_con3_save[APLL_ID] | (RK3288_PLL_BYPASS_MSK << 16)
+ , RK3288_PLL_CONS(APLL_ID, 3));
+ cru_writel(plls_con3_save[GPLL_ID] | (RK3288_PLL_BYPASS_MSK << 16)
+ , RK3288_PLL_CONS(GPLL_ID, 3));
+ cru_writel(plls_con3_save[CPLL_ID] | (RK3288_PLL_BYPASS_MSK << 16)
+ , RK3288_PLL_CONS(CPLL_ID, 3));
+ cru_writel(plls_con3_save[NPLL_ID] | (RK3288_PLL_BYPASS_MSK << 16)
+ , RK3288_PLL_CONS(NPLL_ID, 3));
}
static u32 clk_sel0,clk_sel1, clk_sel10,clk_sel26,clk_sel33,clk_sel36, clk_sel37;
static void pm_plls_resume(void)
{
+ /* core_m0 core_mp a12_core*/
+ cru_writel(clk_sel0 | (CRU_W_MSK(0, 0xf) | CRU_W_MSK(4, 0xf)
+ | CRU_W_MSK(8, 0xf)), RK3288_CRU_CLKSELS_CON(0));
+ /*core0 core1 core2 core3*/
+ cru_writel(clk_sel36 | (CRU_W_MSK(0, 0x7) | CRU_W_MSK(4, 0x7)
+ | CRU_W_MSK(8, 0x7) | CRU_W_MSK(12, 0x7)), RK3288_CRU_CLKSELS_CON(36));
+ /* l2ram atclk pclk*/
+ cru_writel(clk_sel37 | (CRU_W_MSK(0, 0x7) | CRU_W_MSK(4, 0x1f)
+ | CRU_W_MSK(9, 0x1f)), RK3288_CRU_CLKSELS_CON(37));
+
+ /*resume APLL_ID GPLL_ID CPLL_ID NPLL_ID*/
+ plls_resume();
+
+ cru_writel(cru_mode_con | (RK3288_PLL_MODE_MSK(APLL_ID) << 16)
+ , RK3288_CRU_MODE_CON);
+
+ /*peri aclk hclk pclk*/
+ cru_writel(clk_sel10 | (CRU_W_MSK(0, 0x1f) | CRU_W_MSK(8, 0x3)
+ | CRU_W_MSK(12, 0x3)), RK3288_CRU_CLKSELS_CON(10));
+ /*pd bus gpll sel*/
+ cru_writel(clk_sel1 | CRU_W_MSK(15, 0x1), RK3288_CRU_CLKSELS_CON(1));
+ /*pd_bus clk 8*/
+ cru_writel(clk_sel1 | (CRU_W_MSK(0, 0x7) | CRU_W_MSK(3, 0x1f)
+ | CRU_W_MSK(8, 0x3) | CRU_W_MSK(12, 0x7)), RK3288_CRU_CLKSELS_CON(1));
+
+ /*crypto*/
+ cru_writel(clk_sel26 | CRU_W_MSK(6, 0x3), RK3288_CRU_CLKSELS_CON(26));
+
+ /*pmu alive */
+ cru_writel(clk_sel33 | CRU_W_MSK(0, 0x1f) | CRU_W_MSK(8, 0x1f)
+ , RK3288_CRU_CLKSELS_CON(33));
+ cru_writel(cru_mode_con | (RK3288_PLL_MODE_MSK(GPLL_ID) << 16)
+ , RK3288_CRU_MODE_CON);
+ cru_writel(cru_mode_con | (RK3288_PLL_MODE_MSK(CPLL_ID) << 16)
+ , RK3288_CRU_MODE_CON);
+ cru_writel(cru_mode_con | (RK3288_PLL_MODE_MSK(NPLL_ID) << 16)
+ , RK3288_CRU_MODE_CON);
-
- // core_m0 core_mp a12_core
- cru_writel(clk_sel0|(CRU_W_MSK(0,0xf)|CRU_W_MSK(4,0xf)|CRU_W_MSK(8,0xf)),RK3288_CRU_CLKSELS_CON(0));
- // core0 core1 core2 core3
- cru_writel(clk_sel36|(CRU_W_MSK(0,0x7)|CRU_W_MSK(4,0x7)|CRU_W_MSK(8,0x7)|CRU_W_MSK(12,0x7))
- , RK3288_CRU_CLKSELS_CON(36));
- // l2ram atclk pclk
- cru_writel(clk_sel37|(CRU_W_MSK(0,0x7)|CRU_W_MSK(4,0x1f)|CRU_W_MSK(9,0x1f)) , RK3288_CRU_CLKSELS_CON(37));
-
- plls_resume(APLL_ID);
- cru_writel(cru_mode_con|(RK3288_PLL_MODE_MSK(APLL_ID)<<16), RK3288_CRU_MODE_CON);
-
- // peri aclk hclk pclk
- cru_writel(clk_sel10|(CRU_W_MSK(0,0x1f)|CRU_W_MSK(8,0x3)|CRU_W_MSK(12,0x3))
- , RK3288_CRU_CLKSELS_CON(10));
- //pd bus gpll sel
- cru_writel(clk_sel1|CRU_W_MSK(15,0x1), RK3288_CRU_CLKSELS_CON(1));
- // pd_bus clk
- cru_writel(clk_sel1|(CRU_W_MSK(0,0x7)|CRU_W_MSK(3,0x1f)|CRU_W_MSK(8,0x3)|CRU_W_MSK(12,0x7))
- , RK3288_CRU_CLKSELS_CON(1));
-
- // crypto
- cru_writel(clk_sel26|CRU_W_MSK(6,0x3), RK3288_CRU_CLKSELS_CON(26));
-
-
- // pmu alive
- cru_writel(clk_sel33|CRU_W_MSK(0,0x1f)|CRU_W_MSK(8,0x1f), RK3288_CRU_CLKSELS_CON(33));
-
- plls_resume(GPLL_ID);
- cru_writel(cru_mode_con|(RK3288_PLL_MODE_MSK(GPLL_ID)<<16), RK3288_CRU_MODE_CON);
-
- plls_resume(CPLL_ID);
- cru_writel(cru_mode_con|(RK3288_PLL_MODE_MSK(CPLL_ID)<<16), RK3288_CRU_MODE_CON);
-
- plls_resume(NPLL_ID);
- cru_writel(cru_mode_con|(RK3288_PLL_MODE_MSK(NPLL_ID)<<16), RK3288_CRU_MODE_CON);
-
- // rkpm_ddr_regs_dump(RK_CRU_VIRT,RK3288_PLL_CONS((0), 0),RK3288_PLL_CONS((4), 3));
- // rkpm_ddr_regs_dump(RK_CRU_VIRT,RK3288_CRU_MODE_CON,RK3288_CRU_MODE_CON);
- // rkpm_ddr_regs_dump(RK_CRU_VIRT,RK3288_CRU_CLKSELS_CON(0),RK3288_CRU_CLKSELS_CON(42));
-
}
static __sramdata u32 sysclk_clksel0_con,sysclk_clksel1_con,sysclk_clksel10_con,sysclk_mode_con;
}
if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM2)) {
- FUNC(sram_printch)('p');
- FUNC(sram_printch)('o');
- FUNC(sram_printch)('l');
- rkpm_pwm_duty2 = readl_relaxed(RK_PWM_VIRT + 0x28);
- writel_relaxed(PWM_VOLTAGE, RK_PWM_VIRT + 0x28);
+ rkpm_pwm_duty2 = readl_relaxed(RK_PWM_VIRT + 0x28);
+ writel_relaxed(PWM_VOLTAGE, RK_PWM_VIRT + 0x28);
}
- rkpm_udelay(30);
+ //rkpm_udelay(30);
}
void PIE_FUNC(pwm_regulator_resume)(void)
dsb();
rk312x_boot_mode_init();
+ rockchip_efuse_init();
}
static void __init rk3126_dt_map_io(void)
#include <linux/rockchip/grf.h>
#include <linux/rockchip/iomap.h>
#include <linux/rockchip/pmu.h>
+#include <linux/fb.h>
#include <asm/cpuidle.h>
#include <asm/cputype.h>
#include <asm/mach/arch.h>
if (ret)
pr_err("%s: failed to register cpuidle driver: %d\n", __func__, ret);
}
+
+static int rk3288_pll_early_suspend_notifier_call(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ struct fb_event *event = data;
+ int blank_mode = *((int *)event->data);
+
+ if (action == FB_EARLY_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ clk_prepare_enable(clk_get_sys(NULL, "clk_cpll"));
+ clk_prepare_enable(clk_get_sys(NULL, "clk_npll"));
+ break;
+ default:
+ break;
+ }
+ } else if (action == FB_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_POWERDOWN:
+ clk_disable_unprepare(clk_get_sys(NULL, "clk_cpll"));
+ clk_disable_unprepare(clk_get_sys(NULL, "clk_npll"));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block rk3288_pll_early_suspend_notifier = {
+ .notifier_call = rk3288_pll_early_suspend_notifier_call,
+};
+
#ifdef CONFIG_PM
static void __init rk3288_init_suspend(void);
#endif
static void __init rk3288_init_suspend(void)
{
printk("%s\n",__FUNCTION__);
+ fb_register_client(&rk3288_pll_early_suspend_notifier);
rockchip_suspend_init();
rkpm_pie_init();
rk3288_suspend_init();
- rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend,rk_pm_soc_pd_resume);
+ rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend,rk_pm_soc_pd_resume);
}
#if 0
u32 powerdown = INVALID_GPIO,power = INVALID_GPIO,reset = INVALID_GPIO;
u32 af = INVALID_GPIO,flash = INVALID_GPIO;
- int pwr_active = 0, rst_active = 0, pwdn_active = 0;
+ int pwr_active = 0, rst_active = 0, pwdn_active = 0,flash_active = 0;
int orientation = 0;
struct rkcamera_platform_data *new_camera;
}
if (of_property_read_u32(cp, "rockchip,flash", &flash)) {
dprintk("%s:Get %s rockchip,flash failed!\n",__func__, cp->name);
+ }
+ if (of_property_read_u32(cp, "flash_active", &flash_active)) {
+ dprintk("%s:Get %s flash_active failed!\n",__func__, cp->name);
}
if (of_property_read_u32(cp, "i2c_add", &i2c_add)) {
printk("%s:Get %s rockchip,i2c_add failed!\n",__func__, cp->name);
new_camera->io.gpio_power = power;
new_camera->io.gpio_af = af;
new_camera->io.gpio_flash = flash;
- new_camera->io.gpio_flag = ((pwr_active&0x01)<<RK29_CAM_POWERACTIVE_BITPOS)|((rst_active&0x01)<<RK29_CAM_RESETACTIVE_BITPOS)|((pwdn_active&0x01)<<RK29_CAM_POWERDNACTIVE_BITPOS);
+ new_camera->io.gpio_flag = ((pwr_active&0x01)<<RK29_CAM_POWERACTIVE_BITPOS)
+ |((rst_active&0x01)<<RK29_CAM_RESETACTIVE_BITPOS)
+ |((pwdn_active&0x01)<<RK29_CAM_POWERDNACTIVE_BITPOS)
+ |((flash_active&0x01)<<RK29_CAM_FLASHACTIVE_BITPOS);
new_camera->orientation = orientation;
new_camera->resolution = resolution;
new_camera->mirror = mir;
debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
-
if (camera_flash != INVALID_GPIO) {
if (camera_io_init & RK29_CAM_FLASHACTIVE_MASK) {
switch (on)
#include <media/soc_camera.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include "rk_camera_sensor_info.h"
#define RK29_CAM_PLATFORM_DEV_ID 33
#define RK_CAM_PLATFORM_DEV_ID_0 RK29_CAM_PLATFORM_DEV_ID
#define RK29_CAM_FLASHACTIVE_BITPOS 0x03
#define RK29_CAM_AFACTIVE_BITPOS 0x04
-#define RK_CAM_NUM 0 //YZM
-#define RK29_CAM_SUPPORT_NUMS RK_CAM_NUM
#define RK_CAM_SUPPORT_RESOLUTION 0x800000
#define _CONS(a,b) a##b
/*---------------- Camera Sensor Must Define Macro Begin ------------------------*/
-
-#define RK29_CAM_SENSOR_OV7675 ov7675
-#define RK29_CAM_SENSOR_OV9650 ov9650
-#define RK29_CAM_SENSOR_OV2640 ov2640
-#define RK29_CAM_SENSOR_OV2655 ov2655
-#define RK29_CAM_SENSOR_OV2659 ov2659
-
-#define RK29_CAM_SENSOR_OV2660 ov2660 /*yzm*/
-
-#define RK29_CAM_SENSOR_OV7690 ov7690
-#define RK29_CAM_SENSOR_OV3640 ov3640
-#define RK29_CAM_SENSOR_OV3660 ov3660
-#define RK29_CAM_SENSOR_OV5640 ov5640
-#define RK29_CAM_SENSOR_OV5642 ov5642
-#define RK29_CAM_SENSOR_S5K6AA s5k6aa
-#define RK29_CAM_SENSOR_MT9D112 mt9d112
-#define RK29_CAM_SENSOR_MT9D113 mt9d113
-#define RK29_CAM_SENSOR_MT9P111 mt9p111
-#define RK29_CAM_SENSOR_MT9T111 mt9t111
-#define RK29_CAM_SENSOR_GT2005 gt2005
-#define RK29_CAM_SENSOR_GC0307 gc0307
-#define RK29_CAM_SENSOR_GC0308 gc0308
-#define RK29_CAM_SENSOR_GC0309 gc0309
-#define RK29_CAM_SENSOR_GC2015 gc2015
-#define RK29_CAM_SENSOR_GC0328 gc0328
-#define RK29_CAM_SENSOR_GC0329 gc0329
-#define RK29_CAM_SENSOR_GC2035 gc2035
-#define RK29_CAM_SENSOR_SIV120B siv120b
-#define RK29_CAM_SENSOR_SIV121D siv121d
-#define RK29_CAM_SENSOR_SID130B sid130B
-#define RK29_CAM_SENSOR_HI253 hi253
-#define RK29_CAM_SENSOR_HI704 hi704
-#define RK29_CAM_SENSOR_NT99250 nt99250
-#define RK29_CAM_SENSOR_SP0718 sp0718
-#define RK29_CAM_SENSOR_SP0838 sp0838
-#define RK29_CAM_SENSOR_SP2518 sp2518
-#define RK29_CAM_SENSOR_S5K5CA s5k5ca
-#define RK29_CAM_ISP_MTK9335 mtk9335isp
-#define RK29_CAM_SENSOR_HM2057 hm2057
-#define RK29_CAM_SENSOR_HM5065 hm5065
-#define RK29_CAM_SENSOR_NT99160 nt99160 //oyyf@rock-chips.com
-#define RK29_CAM_SENSOR_NT99240 nt99240 //oyyf@rock-chips.com
-#define RK29_CAM_SENSOR_NT99252 nt99252 //oyyf@rock-chips.com
-#define RK29_CAM_SENSOR_NT99340 nt99340 //oyyf@rock-chips.com
-#define RK29_CAM_ISP_ICATCH7002_MI1040 icatchmi1040
-#define RK29_CAM_ISP_ICATCH7002_OV5693 icatchov5693
-#define RK29_CAM_ISP_ICATCH7002_OV8825 icatchov8825 //zyt
-#define RK29_CAM_ISP_ICATCH7002_OV2720 icatchov2720 //zyt
-
-#define RK29_CAM_SENSOR_NAME_OV7675 "ov7675"
-#define RK29_CAM_SENSOR_NAME_OV9650 "ov9650"
-#define RK29_CAM_SENSOR_NAME_OV2640 "ov2640"
-#define RK29_CAM_SENSOR_NAME_OV2655 "ov2655"
-#define RK29_CAM_SENSOR_NAME_OV2659 "ov2659"
-
-#define RK29_CAM_SENSOR_NAME_OV2660 "ov2660" /*yzm*/
-
-
-#define RK29_CAM_SENSOR_NAME_OV7690 "ov7690"
-#define RK29_CAM_SENSOR_NAME_OV3640 "ov3640"
-#define RK29_CAM_SENSOR_NAME_OV3660 "ov3660"
-#define RK29_CAM_SENSOR_NAME_OV5640 "ov5640"
-#define RK29_CAM_SENSOR_NAME_OV5642 "ov5642"
-#define RK29_CAM_SENSOR_NAME_S5K6AA "s5k6aa"
-#define RK29_CAM_SENSOR_NAME_MT9D112 "mt9d112"
-#define RK29_CAM_SENSOR_NAME_MT9D113 "mt9d113"
-#define RK29_CAM_SENSOR_NAME_MT9P111 "mt9p111"
-#define RK29_CAM_SENSOR_NAME_MT9T111 "mt9t111"
-#define RK29_CAM_SENSOR_NAME_GT2005 "gt2005"
-#define RK29_CAM_SENSOR_NAME_GC0307 "gc0307"
-#define RK29_CAM_SENSOR_NAME_GC0308 "gc0308"
-#define RK29_CAM_SENSOR_NAME_GC0309 "gc0309"
-#define RK29_CAM_SENSOR_NAME_GC2015 "gc2015"
-#define RK29_CAM_SENSOR_NAME_GC0328 "gc0328"
-#define RK29_CAM_SENSOR_NAME_GC2035 "gc2035"
-#define RK29_CAM_SENSOR_NAME_GC0329 "gc0329"
-#define RK29_CAM_SENSOR_NAME_SIV120B "siv120b"
-#define RK29_CAM_SENSOR_NAME_SIV121D "siv121d"
-#define RK29_CAM_SENSOR_NAME_SID130B "sid130B"
-#define RK29_CAM_SENSOR_NAME_HI253 "hi253"
-#define RK29_CAM_SENSOR_NAME_HI704 "hi704"
-#define RK29_CAM_SENSOR_NAME_NT99250 "nt99250"
-#define RK29_CAM_SENSOR_NAME_SP0718 "sp0718"
-#define RK29_CAM_SENSOR_NAME_SP0838 "sp0838"
-#define RK29_CAM_SENSOR_NAME_SP2518 "sp2518"
-#define RK29_CAM_SENSOR_NAME_S5K5CA "s5k5ca"
-#define RK29_CAM_ISP_NAME_MTK9335ISP "mtk9335isp"
-#define RK29_CAM_SENSOR_NAME_HM2057 "hm2057"
-#define RK29_CAM_SENSOR_NAME_HM5065 "hm5065"
-#define RK29_CAM_ISP_NAME_ICATCH7002_MI1040 "icatchmi1040"
-#define RK29_CAM_ISP_NAME_ICATCH7002_OV5693 "icatchov5693"
-#define RK29_CAM_ISP_NAME_ICATCH7002_OV8825 "icatchov8825" //zyt
-#define RK29_CAM_ISP_NAME_ICATCH7002_OV2720 "icatchov2720" //zyt
-
-//Sensor full resolution define
-#define ov7675_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define ov9650_FULL_RESOLUTION 0x130000 // 1.3 megapixel
-#define ov2640_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define ov2655_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define ov2659_FULL_RESOLUTION 0x200000 // 2 megapixel
-
-#define ov2660_FULL_RESOLUTION 0x200000 // 2 megapixel
-
-#define ov7690_FULL_RESOLUTION 0x300000 // 2 megapixel
-#define ov3640_FULL_RESOLUTION 0x300000 // 3 megapixel
-#define ov3660_FULL_RESOLUTION 0x300000 // 3 megapixel
-#define ov5640_FULL_RESOLUTION 0x500000 // 5 megapixel
-#if defined(CONFIG_SOC_CAMERA_OV5642_INTERPOLATION_8M)
- #define ov5642_FULL_RESOLUTION 0x800000 // 8 megapixel
-#else
- #define ov5642_FULL_RESOLUTION 0x500000 // 5 megapixel
-#endif
-#define s5k6aa_FULL_RESOLUTION 0x130000 // 1.3 megapixel
-#define mt9d112_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define mt9d113_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define mt9t111_FULL_RESOLUTION 0x300000 // 3 megapixel
-#define mt9p111_FULL_RESOLUTION 0x500000 // 5 megapixel
-#define gt2005_FULL_RESOLUTION 0x200000 // 2 megapixel
-#if defined(CONFIG_SOC_CAMERA_GC0308_INTERPOLATION_5M)
- #define gc0308_FULL_RESOLUTION 0x500000 // 5 megapixel
-#elif defined(CONFIG_SOC_CAMERA_GC0308_INTERPOLATION_3M)
- #define gc0308_FULL_RESOLUTION 0x300000 // 3 megapixel
-#elif defined(CONFIG_SOC_CAMERA_GC0308_INTERPOLATION_2M)
- #define gc0308_FULL_RESOLUTION 0x200000 // 2 megapixel
-#else
- #define gc0308_FULL_RESOLUTION 0x30000 // 0.3 megapixel#endif
-#endif
-#define gc0328_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define gc0307_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define gc0309_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define gc2015_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define siv120b_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define siv121d_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define sid130B_FULL_RESOLUTION 0x200000 // 2 megapixel
-
-#if defined(CONFIG_SOC_CAMERA_HI253_INTERPOLATION_5M)
- #define hi253_FULL_RESOLUTION 0x500000 // 5 megapixel
-#elif defined(CONFIG_SOC_CAMERA_HI253_INTERPOLATION_3M)
- #define hi253_FULL_RESOLUTION 0x300000 // 3 megapixel
-#else
- #define hi253_FULL_RESOLUTION 0x200000 // 2 megapixel
-#endif
-
-#define hi704_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define nt99250_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define sp0718_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define sp0838_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define sp2518_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define gc0329_FULL_RESOLUTION 0x30000 // 0.3 megapixel
-#define s5k5ca_FULL_RESOLUTION 0x300000 // 3 megapixel
-#define mtk9335isp_FULL_RESOLUTION 0x500000 //5 megapixel
-#define gc2035_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define hm2057_FULL_RESOLUTION 0x200000 // 2 megapixel
-#define hm5065_FULL_RESOLUTION 0x500000 // 5 megapixel
-#define nt99160_FULL_RESOLUTION 0x100000 // oyyf@rock-chips.com: 1 megapixel 1280*720
-#define nt99240_FULL_RESOLUTION 0x200000 // oyyf@rock-chips.com: 2 megapixel 1600*1200
-#define nt99252_FULL_RESOLUTION 0x200000 // oyyf@rock-chips.com: 2 megapixel 1600*1200
-#define nt99340_FULL_RESOLUTION 0x300000 // oyyf@rock-chips.com: 3 megapixel 2048*1536
-#define icatchmi1040_FULL_RESOLUTION 0x200000
-#define icatchov5693_FULL_RESOLUTION 0x500000
-#define icatchov8825_FULL_RESOLUTION 0x800000 //zyt
-#define icatchov2720_FULL_RESOLUTION 0x210000 //zyt
-#define end_FULL_RESOLUTION 0x00
-
-//Sensor i2c addr define
-#define ov7675_I2C_ADDR 0x78
-#define ov9650_I2C_ADDR 0x60
-#define ov2640_I2C_ADDR 0x60
-#define ov2655_I2C_ADDR 0x60
-#define ov2659_I2C_ADDR 0x60
-
-#define ov2660_I2C_ADDR 0x60 /*yzm*/
-
-#define ov7690_I2C_ADDR 0x42
-#define ov3640_I2C_ADDR 0x78
-#define ov3660_I2C_ADDR 0x78
-#define ov5640_I2C_ADDR 0x78
-#define ov5642_I2C_ADDR 0x78
-
-#define s5k6aa_I2C_ADDR 0x78 //0x5a
-#define s5k5ca_I2C_ADDR 0x78 //0x5a
-
-#define mt9d112_I2C_ADDR 0x78
-#define mt9d113_I2C_ADDR 0x78
-#define mt9t111_I2C_ADDR 0x78 // 0x7a
-
-#define mt9p111_I2C_ADDR 0x78 //0x7a
-#define gt2005_I2C_ADDR 0x78
-#define gc0307_I2C_ADDR 0x42
-#define gc0328_I2C_ADDR 0x42
-#define gc0308_I2C_ADDR 0x42
-#define gc0309_I2C_ADDR 0x42
-#define gc0329_I2C_ADDR 0x62
-#define gc2015_I2C_ADDR 0x60
-#define gc2035_I2C_ADDR 0x78
-
-#define siv120b_I2C_ADDR INVALID_VALUE
-#define siv121d_I2C_ADDR INVALID_VALUE
-#define sid130B_I2C_ADDR 0x37
-
-#define hi253_I2C_ADDR 0x40
-#define hi704_I2C_ADDR 0x60
-
-#define nt99160_I2C_ADDR 0x54
-#define nt99240_I2C_ADDR 0x6c
-#define nt99250_I2C_ADDR 0x6c
-#define nt99252_I2C_ADDR 0x6c
-#define nt99340_I2C_ADDR 0x76
-
-#define sp0718_I2C_ADDR 0x42
-#define sp0838_I2C_ADDR INVALID_VALUE
-#define sp0a19_I2C_ADDR 0x7a
-#define sp1628_I2C_ADDR 0x78
-#define sp2518_I2C_ADDR 0x60
-#define mtk9335isp_I2C_ADDR 0x50
-#define hm2057_I2C_ADDR 0x48
-#define hm5065_I2C_ADDR 0x3e
-#define icatchmi1040_I2C_ADDR 0x78
-#define icatchov5693_I2C_ADDR 0x78
-#define icatchov8825_I2C_ADDR 0x78 //zyt
-#define icatchov2720_I2C_ADDR 0x78 //zyt
-#define end_I2C_ADDR INVALID_VALUE
-
-
-//Sensor power down active level define
-#define ov7675_PWRDN_ACTIVE 0x01
-#define ov9650_PWRDN_ACTIVE 0x01
-#define ov2640_PWRDN_ACTIVE 0x01
-#define ov2655_PWRDN_ACTIVE 0x01
-#define ov2659_PWRDN_ACTIVE 0x01
-
-#define ov2660_PWRDN_ACTIVE 0x01 /*yzm*/
-
-#define ov7690_PWRDN_ACTIVE 0x01
-#define ov3640_PWRDN_ACTIVE 0x01
-#define ov3660_PWRDN_ACTIVE 0x01
-#define ov5640_PWRDN_ACTIVE 0x01
-#define ov5642_PWRDN_ACTIVE 0x01
-
-#define s5k6aa_PWRDN_ACTIVE 0x00
-#define s5k5ca_PWRDN_ACTIVE 0x00
-
-#define mt9d112_PWRDN_ACTIVE 0x01
-#define mt9d113_PWRDN_ACTIVE 0x01
-#define mt9t111_PWRDN_ACTIVE 0x01
-#define mt9p111_PWRDN_ACTIVE 0x01
-
-#define gt2005_PWRDN_ACTIVE 0x00
-#define gc0307_PWRDN_ACTIVE 0x01
-#define gc0308_PWRDN_ACTIVE 0x01
-#define gc0328_PWRDN_ACTIVE 0x01
-#define gc0309_PWRDN_ACTIVE 0x01
-#define gc0329_PWRDN_ACTIVE 0x01
-#define gc2015_PWRDN_ACTIVE 0x01
-#define gc2035_PWRDN_ACTIVE 0x01
-
-#define siv120b_PWRDN_ACTIVE INVALID_VALUE
-#define siv121d_PWRDN_ACTIVE INVALID_VALUE
-#define sid130B_PWRDN_ACTIVE 0x37
-
-#define hi253_PWRDN_ACTIVE 0x01
-#define hi704_PWRDN_ACTIVE 0x01
-
-#define nt99160_PWRDN_ACTIVE 0x01
-#define nt99240_PWRDN_ACTIVE 0x01
-#define nt99250_PWRDN_ACTIVE 0x01
-#define nt99252_PWRDN_ACTIVE 0x01
-#define nt99340_PWRDN_ACTIVE 0x01
-
-#define sp0718_PWRDN_ACTIVE 0x01
-#define sp0838_PWRDN_ACTIVE 0x01
-#define sp0a19_PWRDN_ACTIVE 0x01
-#define sp1628_PWRDN_ACTIVE 0x01
-#define sp2518_PWRDN_ACTIVE 0x01
-#define hm2057_PWRDN_ACTIVE 0x01
-#define hm5065_PWRDN_ACTIVE 0x00
-#define mtk9335isp_PWRDN_ACTIVE 0x01
-#define end_PWRDN_ACTIVE INVALID_VALUE
-
-
-//Sensor power up sequence define
-//type: bit0-bit4
-#define SENSOR_PWRSEQ_BEGIN 0x00
-#define SENSOR_PWRSEQ_AVDD 0x01
-#define SENSOR_PWRSEQ_DOVDD 0x02
-#define SENSOR_PWRSEQ_DVDD 0x03
-#define SENSOR_PWRSEQ_PWR 0x04
-#define SENSOR_PWRSEQ_HWRST 0x05
-#define SENSOR_PWRSEQ_PWRDN 0x06
-#define SENSOR_PWRSEQ_CLKIN 0x07
-#define SENSOR_PWRSEQ_END 0x0F
-
-#define SENSOR_PWRSEQ_SET(type,idx) (type<<(idx*4))
-#define SENSOR_PWRSEQ_GET(seq,idx) ((seq>>(idx*4))&0x0f)
-
-#define sensor_PWRSEQ_DEFAULT (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,1)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWRDN,2)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,3))
-
-#define ov7675_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov9650_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov2640_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov2655_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov2659_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define ov2660_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define ov7690_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov3640_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov3660_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov5640_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define ov5642_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define s5k6aa_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define s5k5ca_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define mt9d112_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define mt9d113_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define mt9t111_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define mt9p111_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define gt2005_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc0307_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc0308_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc0328_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc0309_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc0329_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc2015_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define gc2035_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define siv120b_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define siv121d_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define sid130B_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define hi253_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define hi704_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define nt99160_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define nt99240_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define nt99250_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define nt99252_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define nt99340_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define sp0718_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define sp0838_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define sp0a19_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define sp1628_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define sp2518_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define hm2057_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define hm5065_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,1)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWRDN,0)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,3))
-#define mtk9335isp_PWRSEQ sensor_PWRSEQ_DEFAULT
-#define icatchov5693_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,1))
-
-#define icatchov8825_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,1)) //zyt
-
-#define icatchov2720_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,1)) //zyt
-
-#define icatchmi1040_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\
- SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,1))
-
-#define end_PWRSEQ 0xffffffff
-
-
-
+/*
+ move to rk_camera_sensor_info.h yzm
+*/
/*---------------- Camera Sensor Must Define Macro End ------------------------*/
#define RK29_CAM_SENSOR_OV2640 ov2640
#define RK29_CAM_SENSOR_OV2655 ov2655
#define RK29_CAM_SENSOR_OV2659 ov2659
-
-#define RK29_CAM_SENSOR_OV2660 ov2660 /*yzm*/
-
#define RK29_CAM_SENSOR_OV7690 ov7690
#define RK29_CAM_SENSOR_OV3640 ov3640
#define RK29_CAM_SENSOR_OV3660 ov3660
#define RK29_CAM_SENSOR_NAME_OV2640 "ov2640"
#define RK29_CAM_SENSOR_NAME_OV2655 "ov2655"
#define RK29_CAM_SENSOR_NAME_OV2659 "ov2659"
-
-#define RK29_CAM_SENSOR_NAME_OV2660 "ov2660" /*yzm*/
-
-
#define RK29_CAM_SENSOR_NAME_OV7690 "ov7690"
#define RK29_CAM_SENSOR_NAME_OV3640 "ov3640"
#define RK29_CAM_SENSOR_NAME_OV3660 "ov3660"
#define ov2640_I2C_ADDR 0x60
#define ov2655_I2C_ADDR 0x60
#define ov2659_I2C_ADDR 0x60
-
-#define ov2660_I2C_ADDR 0x60 /*yzm*/
-
#define ov7690_I2C_ADDR 0x42
#define ov3640_I2C_ADDR 0x78
#define ov3660_I2C_ADDR 0x78
#define ov2640_PWRDN_ACTIVE 0x01
#define ov2655_PWRDN_ACTIVE 0x01
#define ov2659_PWRDN_ACTIVE 0x01
-
-#define ov2660_PWRDN_ACTIVE 0x01 /*yzm*/
-
#define ov7690_PWRDN_ACTIVE 0x01
#define ov3640_PWRDN_ACTIVE 0x01
#define ov3660_PWRDN_ACTIVE 0x01
#define ov2640_PWRSEQ sensor_PWRSEQ_DEFAULT
#define ov2655_PWRSEQ sensor_PWRSEQ_DEFAULT
#define ov2659_PWRSEQ sensor_PWRSEQ_DEFAULT
-
-#define ov2660_PWRSEQ sensor_PWRSEQ_DEFAULT
-
#define ov7690_PWRSEQ sensor_PWRSEQ_DEFAULT
#define ov3640_PWRSEQ sensor_PWRSEQ_DEFAULT
#define ov3660_PWRSEQ sensor_PWRSEQ_DEFAULT
struct delayed_work simulate_work;
} vpu_service_info;
+struct vcodec_combo {
+ struct vpu_service_info *vpu_srv;
+ struct vpu_service_info *hevc_srv;
+};
+
typedef struct vpu_request
{
unsigned long *req;
static struct dentry *parent; // debugfs root directory for all device (vpu, hevc).
/* mutex for selecting operation registers of vpu or hevc */
static struct mutex g_mode_mutex;
+static struct vcodec_combo g_combo;
#ifdef CONFIG_DEBUG_FS
static int vcodec_debugfs_init(void);
vpu_queue_power_off_work(pservice);
last = now;
}
+
if (pservice->enabled)
return ;
pservice->enabled = true;
printk("%s: power on\n", dev_name(pservice->dev));
+ if (cpu_is_rk3036() || cpu_is_rk312x()) {
+ if (pservice == g_combo.vpu_srv) {
+ if (g_combo.hevc_srv != NULL && g_combo.hevc_srv->mmu_dev) {
+ u32 config;
+ vcodec_enter_mode_nolock(g_combo.hevc_srv->dev_id, &config);
+ rockchip_iovmm_deactivate(g_combo.hevc_srv->dev);
+ vcodec_exit_mode_nolock(g_combo.hevc_srv->dev_id, config);
+ }
+ } else if (pservice == g_combo.hevc_srv) {
+ if (g_combo.vpu_srv != NULL && g_combo.vpu_srv->mmu_dev) {
+ u32 config;
+ vcodec_enter_mode_nolock(g_combo.vpu_srv->dev_id, &config);
+ rockchip_iovmm_deactivate(g_combo.vpu_srv->dev);
+ vcodec_exit_mode_nolock(g_combo.vpu_srv->dev_id, config);
+ }
+ }
+ }
+
#if VCODEC_CLOCK_ENABLE
if (pservice->aclk_vcodec)
clk_prepare_enable(pservice->aclk_vcodec);
wake_lock(&pservice->wake_lock);
#if defined(CONFIG_VCODEC_MMU)
- if (pservice->mmu_dev)
+ if (pservice->mmu_dev) {
+ vcodec_enter_mode(pservice->dev_id);
rockchip_iovmm_activate(pservice->dev);
+ vcodec_exit_mode();
+ }
#endif
}
struct device_node *np = pdev->dev.of_node;
struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);
char *prop = (char*)dev_name(dev);
+ u32 config;
#if defined(CONFIG_VCODEC_MMU)
u32 iommu_en = 0;
char mmu_dev_dts_name[40];
if (strcmp(dev_name(dev), "hevc_service") == 0) {
pservice->dev_id = VCODEC_DEVICE_ID_HEVC;
+ g_combo.hevc_srv = pservice;
} else if (strcmp(dev_name(dev), "vpu_service") == 0) {
pservice->dev_id = VCODEC_DEVICE_ID_VPU;
+ g_combo.vpu_srv = pservice;
} else {
dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));
return -1;
}
mutex_init(&g_mode_mutex);
- vcodec_enter_mode(pservice->dev_id);
+ vcodec_enter_mode_nolock(pservice->dev_id, &config);
wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");
INIT_LIST_HEAD(&pservice->waiting);
rockchip_iovmm_set_fault_handler(pservice->dev, vcodec_sysmmu_fault_handler);
}
#endif
- vcodec_exit_mode();
+ vcodec_exit_mode_nolock(pservice->dev_id, config);
vpu_service_power_off(pservice);
pr_info("init success\n");
{
int ret;
+ g_combo.hevc_srv = NULL;
+ g_combo.vpu_srv = NULL;
+
if ((ret = platform_driver_register(&vcodec_driver)) != 0) {
pr_err("Platform device register failed (%d).\n", ret);
return ret;
return file->f_op == &dma_buf_fops;
}
+#ifdef CONFIG_ARCH_ROCKCHIP
+int dma_buf_is_dma_buf(struct file *file)
+{
+ return is_dma_buf_file(file);
+}
+#endif
+
/**
* dma_buf_export_named - Creates a new dma_buf, and associates an anon file
* with this buffer, so it can be exported.
return ret;
}
+static int clk_pll_is_enabled_3188plus(struct clk_hw *hw)
+{
+ unsigned long flags;
+ struct clk_pll *pll = to_clk_pll(hw);
+ int ret;
+
+ if(pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift))
+ ret = 1;
+ else
+ ret = 0;
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static int clk_pll_enable_3188plus(struct clk_hw *hw)
+{
+ struct clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags;
+ unsigned long rst_dly;
+ u32 nr;
+
+ clk_debug("%s enter\n", __func__);
+
+ if (clk_pll_is_enabled_3188plus(hw)) {
+ clk_debug("pll has been enabled\n");
+ return 0;
+ }
+
+ if(pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ //enter slowmode
+ cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
+
+ //power up
+ cru_writel(_RK3188PLUS_PLL_POWERDOWN_SET(0), pll->reg + RK3188_PLL_CON(3));
+
+ //enter reset
+ cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
+
+ //cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
+ //cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
+ //cru_writel(clk_set->pllcon2, pll->reg + RK3188_PLL_CON(2));
+
+ udelay(5);
+
+ //return from reset
+ cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
+
+ //wating lock state
+ nr = RK3188PLUS_PLL_NR(cru_readl(pll->reg + RK3188_PLL_CON(0)));
+ rst_dly = ((nr*500)/24+1);
+ udelay(rst_dly);
+
+ pll_wait_lock(hw);
+
+ //return from slow
+ cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ clk_debug("pll %s dump reg:\n con0=0x%08x,\n con1=0x%08x,\n con2=0x%08x,\n"
+ "con3=0x%08x,\n mode=0x%08x\n",
+ __clk_get_name(hw->clk),
+ cru_readl(pll->reg + RK3188_PLL_CON(0)),
+ cru_readl(pll->reg + RK3188_PLL_CON(1)),
+ cru_readl(pll->reg + RK3188_PLL_CON(2)),
+ cru_readl(pll->reg + RK3188_PLL_CON(3)),
+ cru_readl(pll->mode_offset));
+
+ return 0;
+}
+
+static void clk_pll_disable_3188plus(struct clk_hw *hw)
+{
+ struct clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags;
+
+ clk_debug("%s enter\n", __func__);
+
+ if(pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ //enter slowmode
+ cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
+
+ //power down
+ cru_writel(_RK3188PLUS_PLL_POWERDOWN_SET(1), pll->reg + RK3188_PLL_CON(3));
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+
static const struct clk_ops clk_pll_ops_3188plus = {
.recalc_rate = clk_pll_recalc_rate_3188plus,
.round_rate = clk_pll_round_rate_3188plus,
.set_rate = clk_pll_set_rate_3188plus,
+ .enable = clk_pll_enable_3188plus,
+ .disable = clk_pll_disable_3188plus,
+ .is_enabled = clk_pll_is_enabled_3188plus,
};
/* CLK_PLL_3188PLUS_AUTO type ops */
.recalc_rate = clk_pll_recalc_rate_3188plus_auto,
.round_rate = clk_pll_round_rate_3188plus_auto,
.set_rate = clk_pll_set_rate_3188plus_auto,
+ .enable = clk_pll_enable_3188plus,
+ .disable = clk_pll_disable_3188plus,
+ .is_enabled = clk_pll_is_enabled_3188plus,
};
/* The number of default descriptors */
-#define NR_DEFAULT_DESC 16
+#define NR_DEFAULT_DESC 32
/* Populated by the PL330 core driver for DMA API driver's info */
struct pl330_config {
struct dma_pl330_dmac *pdmac = pch->dmac;
u8 *peri_id = pch->chan.private;
struct dma_pl330_desc *desc;
+ int i = 0;
/* Pluck one desc from the pool of DMAC */
desc = pluck_desc(pdmac);
/* If the DMAC pool is empty, alloc new */
if (!desc) {
- if (!add_desc(pdmac, GFP_ATOMIC, 1))
- return NULL;
+ for(i = 0; i < 3; i++) {
+ if (!add_desc(pdmac, GFP_ATOMIC, 1))
+ continue;
- /* Try again */
- desc = pluck_desc(pdmac);
- if (!desc) {
- dev_err(pch->dmac->pif.dev,
- "%s:%d ALERT!\n", __func__, __LINE__);
- return NULL;
+ /* Try again */
+ desc = pluck_desc(pdmac);
+ if (!desc) {
+ dev_err(pch->dmac->pif.dev,
+ "%s:%d i=%d ALERT!\n", __func__, __LINE__,i);
+ continue;
+ }
+ break;
}
+
+ if(!desc && i >= 3)
+ return NULL;
}
/* Initialize the descriptor */
static void rockchip_i2c_init_hw(struct rockchip_i2c *i2c, unsigned long scl_rate)
{
i2c->scl_rate = 0;
-// clk_prepare_enable(i2c->clk);
+ clk_enable(i2c->clk);
rockchip_i2c_set_clk(i2c, scl_rate);
-// clk_disable_unprepare(i2c->clk);
+ clk_disable(i2c->clk);
}
/* returns TRUE if we this is the last byte in the current message */
struct rockchip_i2c *i2c = i2c_get_adapdata(adap);
unsigned long scl_rate = i2c->scl_rate;
-// clk_prepare_enable(i2c->clk);
+ clk_enable(i2c->clk);
if (i2c->check_idle) {
int state, retry = 10;
while (retry--) {
ret = rockchip_i2c_doxfer(i2c, msgs, num);
i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%04x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state);
-// clk_disable_unprepare(i2c->clk);
+ clk_disable(i2c->clk);
return (ret < 0) ? ret : num;
}
return ret;
}
- clk_prepare_enable(i2c->clk); // FIXME: enable i2c clock temporarily
+ ret = clk_prepare(i2c->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not prepare clock\n");
+ return ret;
+ }
+
i2c->i2c_rate = clk_get_rate(i2c->clk);
rockchip_i2c_init_hw(i2c, 100 * 1000);
struct rockchip_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
+ clk_unprepare(i2c->clk);
return 0;
}
INIT_COMPLETION(info->completion);
+ clk_enable(info->clk);
+ clk_enable(info->pclk);
+
/* Select the channel to be used and Trigger conversion */
writel_relaxed(0x08, info->regs + ADC_DELAY_PU_SOC);
writel_relaxed(ADC_CTRL_POWER_UP|ADC_CTRL_CH(chan->channel)|ADC_CTRL_IRQ_ENABLE, info->regs + ADC_CTRL);
ret = -ETIMEDOUT;
}
+ clk_disable(info->clk);
+ clk_disable(info->pclk);
+
mutex_unlock(&indio_dev->mlock);
return ret;
if (readval == NULL)
return -EINVAL;
+ clk_enable(info->clk);
+ clk_enable(info->pclk);
+
*readval = readl_relaxed(info->regs + reg);
+ clk_disable(info->clk);
+ clk_disable(info->pclk);
+
return 0;
}
ADC_CHANNEL(0, "adc0"),
ADC_CHANNEL(1, "adc1"),
ADC_CHANNEL(2, "adc2"),
- ADC_CHANNEL(3, "adc3"),
+ ADC_CHANNEL(6, "adc6"),
};
static int rk_adc_remove_devices(struct device *dev, void *c)
ret = PTR_ERR(info->pclk);
goto err_iio;
}
- clk_prepare_enable(info->pclk);
+ clk_prepare(info->pclk);
info->clk = devm_clk_get(&pdev->dev, "saradc");
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to set adc clk\n");
goto err_pclk;
}
- clk_prepare_enable(info->clk);
+ clk_prepare(info->clk);
//device register
indio_dev->name = dev_name(&pdev->dev);
iio_device_unregister(indio_dev);
err_clk:
- clk_disable_unprepare(info->clk);
+ clk_unprepare(info->clk);
err_pclk:
- clk_disable_unprepare(info->pclk);
+ clk_unprepare(info->pclk);
err_iio:
iio_device_free(indio_dev);
device_for_each_child(&pdev->dev, NULL,
rk_adc_remove_devices);
- clk_disable_unprepare(info->clk);
- clk_disable_unprepare(info->pclk);
+ clk_unprepare(info->clk);
+ clk_unprepare(info->pclk);
iio_device_unregister(indio_dev);
free_irq(info->irq, info);
iio_device_free(indio_dev);
cpumask_set_cpu(cpu_id, &cpumask);
irq_set_affinity(irq, &cpumask);
ret = devm_request_irq(&pdev->dev, irq, rockchip_pwm_irq,
- 0, "rk_pwm_irq", ddata);
+ IRQF_NO_SUSPEND, "rk_pwm_irq", ddata);
if (ret) {
dev_err(&pdev->dev, "cannot claim IRQ %d\n", irq);
return ret;
IOMMU_FLAGS_MASK = 0x1FF,
};
-#define lv1ent_fault(sent) ((*(sent) & IOMMU_FLAGS_PRESENT) == 0)
-#define lv1ent_page(sent) ((*(sent) & IOMMU_FLAGS_PRESENT) == 1)
-#define lv2ent_fault(pent) ((*(pent) & IOMMU_FLAGS_PRESENT) == 0)
-#define spage_phys(pent) (*(pent) & SPAGE_MASK)
-#define spage_offs(iova) ((iova) & 0x0FFF)
+#define rockchip_lv1ent_fault(sent) ((*(sent) & IOMMU_FLAGS_PRESENT) == 0)
+#define rockchip_lv1ent_page(sent) ((*(sent) & IOMMU_FLAGS_PRESENT) == 1)
+#define rockchip_lv2ent_fault(pent) ((*(pent) & IOMMU_FLAGS_PRESENT) == 0)
+#define rockchip_spage_phys(pent) (*(pent) & SPAGE_MASK)
+#define rockchip_spage_offs(iova) ((iova) & 0x0FFF)
-#define lv1ent_offset(iova) (((iova)>>22) & 0x03FF)
-#define lv2ent_offset(iova) (((iova)>>12) & 0x03FF)
+#define rockchip_lv1ent_offset(iova) (((iova)>>22) & 0x03FF)
+#define rockchip_lv2ent_offset(iova) (((iova)>>12) & 0x03FF)
#define NUM_LV1ENTRIES 1024
#define NUM_LV2ENTRIES 1024
#define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(long))
-#define lv2table_base(sent) (*(sent) & 0xFFFFFFFE)
+#define rockchip_lv2table_base(sent) (*(sent) & 0xFFFFFFFE)
-#define mk_lv1ent_page(pa) ((pa) | IOMMU_FLAGS_PRESENT)
+#define rockchip_mk_lv1ent_page(pa) ((pa) | IOMMU_FLAGS_PRESENT)
/*write and read permission for level2 page default*/
-#define mk_lv2ent_spage(pa) ((pa) | IOMMU_FLAGS_PRESENT | \
+#define rockchip_mk_lv2ent_spage(pa) ((pa) | IOMMU_FLAGS_PRESENT | \
IOMMU_FLAGS_READ_PERMISSION | \
IOMMU_FLAGS_WRITE_PERMISSION)
#define IOMMU_REG_POLL_COUNT_FAST 1000
-/*rk3036:vpu and hevc share ahb interface*/
-#define BIT_VCODEC_SEL_3036 (1<<3)
-#define BIT_VCODEC_SEL_312x (1<<15)
-
-
/**
* MMU register numbers
* Used in the register read/write routines.
static struct kmem_cache *lv2table_kmem_cache;
-static void rockchip_vcodec_select(const char *string)
-{
- if (strstr(string,"hevc")) {
- if (cpu_is_rk3036()) {
- writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) |
- (BIT_VCODEC_SEL_3036) | (BIT_VCODEC_SEL_3036 << 16),
- RK_GRF_VIRT + RK3036_GRF_SOC_CON1);
- } else {
- writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK312X_GRF_SOC_CON1) |
- (BIT_VCODEC_SEL_312x) | (BIT_VCODEC_SEL_312x << 16),
- RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
- }
- } else if (strstr(string,"vpu")) {
- if (cpu_is_rk3036()) {
- writel_relaxed((readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) &
- (~BIT_VCODEC_SEL_3036)) | (BIT_VCODEC_SEL_3036 << 16),
- RK_GRF_VIRT + RK3036_GRF_SOC_CON1);
- } else {
- writel_relaxed((readl_relaxed(RK_GRF_VIRT + RK312X_GRF_SOC_CON1) &
- (~BIT_VCODEC_SEL_312x)) | (BIT_VCODEC_SEL_312x << 16),
- RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
- }
- }
-}
-static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
+static unsigned long *rockchip_section_entry(unsigned long *pgtable, unsigned long iova)
{
- return pgtable + lv1ent_offset(iova);
+ return pgtable + rockchip_lv1ent_offset(iova);
}
-static unsigned long *page_entry(unsigned long *sent, unsigned long iova)
+static unsigned long *rockchip_page_entry(unsigned long *sent, unsigned long iova)
{
- return (unsigned long *)__va(lv2table_base(sent)) + lv2ent_offset(iova);
+ return (unsigned long *)__va(rockchip_lv2table_base(sent)) +
+ rockchip_lv2ent_offset(iova);
}
-static char *iommu_fault_name[IOMMU_FAULTS_NUM] = {
- "PAGE FAULT",
- "BUS ERROR",
- "UNKNOWN FAULT"
-};
-
struct rk_iommu_domain {
struct list_head clients; /* list of iommu_drvdata.node */
unsigned long *pgtable; /* lv1 page table, 4KB */
spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */
};
-static bool set_iommu_active(struct iommu_drvdata *data)
+static bool rockchip_set_iommu_active(struct iommu_drvdata *data)
{
/* return true if the IOMMU was not active previously
and it needs to be initialized */
return ++data->activations == 1;
}
-static bool set_iommu_inactive(struct iommu_drvdata *data)
+static bool rockchip_set_iommu_inactive(struct iommu_drvdata *data)
{
/* return true if the IOMMU is needed to be disabled */
BUG_ON(data->activations < 1);
return --data->activations == 0;
}
-static bool is_iommu_active(struct iommu_drvdata *data)
+static bool rockchip_is_iommu_active(struct iommu_drvdata *data)
{
return data->activations > 0;
}
-static void iommu_disable_stall(void __iomem *base)
+static void rockchip_iommu_disable_stall(void __iomem *base)
{
int i;
u32 mmu_status;
} else {
goto skip_vop_mmu_disable;
}
- if (0 == (mmu_status & IOMMU_STATUS_BIT_PAGING_ENABLED))
+
+ if (0 == (mmu_status & IOMMU_STATUS_BIT_PAGING_ENABLED)) {
return;
+ }
+
if (mmu_status & IOMMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
pr_info("Aborting MMU disable stall request since it is in pagefault state.\n");
return;
}
+
+ if (!(mmu_status & IOMMU_STATUS_BIT_STALL_ACTIVE)) {
+ return;
+ }
+
skip_vop_mmu_disable:
- __raw_writel(IOMMU_COMMAND_DISABLE_STALL,
- base + IOMMU_REGISTER_COMMAND);
+ __raw_writel(IOMMU_COMMAND_DISABLE_STALL, base + IOMMU_REGISTER_COMMAND);
for (i = 0; i < IOMMU_REG_POLL_COUNT_FAST; ++i) {
u32 status;
j++;
return;
}
+
if (0 == (status & IOMMU_STATUS_BIT_STALL_ACTIVE))
break;
+
if (status & IOMMU_STATUS_BIT_PAGE_FAULT_ACTIVE)
break;
+
if (0 == (mmu_status & IOMMU_STATUS_BIT_PAGING_ENABLED))
break;
}
+
if (IOMMU_REG_POLL_COUNT_FAST == i) {
pr_info("Disable stall request failed, MMU status is 0x%08X\n",
__raw_readl(base + IOMMU_REGISTER_STATUS));
}
}
-static bool iommu_enable_stall(void __iomem *base)
+static bool rockchip_iommu_enable_stall(void __iomem *base)
{
int i;
} else {
goto skip_vop_mmu_enable;
}
- if (0 == (mmu_status & IOMMU_STATUS_BIT_PAGING_ENABLED))
+
+ if (0 == (mmu_status & IOMMU_STATUS_BIT_PAGING_ENABLED)) {
+ return true;
+ }
+
+ if (mmu_status & IOMMU_STATUS_BIT_STALL_ACTIVE){
+ pr_info("MMU stall already enabled\n");
return true;
+ }
+
if (mmu_status & IOMMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
- pr_info("Aborting MMU stall request since it is in pagefault state.\n");
+ pr_info("Aborting MMU stall request since it is in pagefault state. mmu status is 0x%08x\n",
+ mmu_status);
return false;
}
+
skip_vop_mmu_enable:
- __raw_writel(IOMMU_COMMAND_ENABLE_STALL,
- base + IOMMU_REGISTER_COMMAND);
+ __raw_writel(IOMMU_COMMAND_ENABLE_STALL, base + IOMMU_REGISTER_COMMAND);
for (i = 0; i < IOMMU_REG_POLL_COUNT_FAST; ++i) {
if (base != rk312x_vop_mmu_base) {
j++;
return true;
}
+
if (mmu_status & IOMMU_STATUS_BIT_PAGE_FAULT_ACTIVE)
break;
+
if ((mmu_status & IOMMU_STATUS_BIT_STALL_ACTIVE) &&
(0 == (mmu_status & IOMMU_STATUS_BIT_STALL_NOT_ACTIVE)))
break;
+
if (0 == (mmu_status & (IOMMU_STATUS_BIT_PAGING_ENABLED)))
break;
}
+
if (IOMMU_REG_POLL_COUNT_FAST == i) {
pr_info("Enable stall request failed, MMU status is 0x%08X\n",
__raw_readl(base + IOMMU_REGISTER_STATUS));
return false;
}
+
if (mmu_status & IOMMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
pr_info("Aborting MMU stall request since it has a pagefault.\n");
return false;
}
+
return true;
}
-static bool iommu_enable_paging(void __iomem *base)
+static bool rockchip_iommu_enable_paging(void __iomem *base)
{
int i;
return true;
}
}
+
if (IOMMU_REG_POLL_COUNT_FAST == i) {
pr_info("Enable paging request failed, MMU status is 0x%08X\n",
__raw_readl(base + IOMMU_REGISTER_STATUS));
return false;
}
+
return true;
}
-static bool iommu_disable_paging(void __iomem *base)
+static bool rockchip_iommu_disable_paging(void __iomem *base)
{
int i;
return true;
}
}
+
if (IOMMU_REG_POLL_COUNT_FAST == i) {
pr_info("Disable paging request failed, MMU status is 0x%08X\n",
__raw_readl(base + IOMMU_REGISTER_STATUS));
return false;
}
+
return true;
}
-static void iommu_page_fault_done(void __iomem *base, const char *dbgname)
+static void rockchip_iommu_page_fault_done(void __iomem *base, const char *dbgname)
{
pr_info("MMU: %s: Leaving page fault mode\n",
dbgname);
__raw_writel(IOMMU_COMMAND_PAGE_FAULT_DONE,
base + IOMMU_REGISTER_COMMAND);
}
-
-static bool iommu_zap_tlb(void __iomem *base)
+#if 1
+static int rockchip_iommu_zap_tlb_without_stall (void __iomem *base)
{
- bool stall_success;
+ __raw_writel(IOMMU_COMMAND_ZAP_CACHE, base + IOMMU_REGISTER_COMMAND);
- if (rk312x_vop_mmu_base != base)
- stall_success = iommu_enable_stall(base);
- else
- stall_success = true;
+ return 0;
+}
+#endif
- __raw_writel(IOMMU_COMMAND_ZAP_CACHE,
- base + IOMMU_REGISTER_COMMAND);
- if (!stall_success)
- return false;
+#if 0
+static int rockchip_iommu_zap_tlb(void __iomem *base)
+{
+ if (!rockchip_iommu_enable_stall(base)) {
+ pr_err("%s failed\n", __func__);
+ return -1;
+ }
- if (rk312x_vop_mmu_base != base)
- iommu_disable_stall(base);
- else
- return true;
+ __raw_writel(IOMMU_COMMAND_ZAP_CACHE, base + IOMMU_REGISTER_COMMAND);
- return true;
+ rockchip_iommu_disable_stall(base);
+
+ return 0;
}
-extern bool __clk_is_enabled(struct clk *clk);
-static inline bool iommu_raw_reset(void __iomem *base)
+#endif
+
+static inline bool rockchip_iommu_raw_reset(void __iomem *base)
{
int i;
unsigned int ret;
+ unsigned int grf_value;
__raw_writel(0xCAFEBABE, base + IOMMU_REGISTER_DTE_ADDR);
if (base != rk312x_vop_mmu_base) {
ret = __raw_readl(base + IOMMU_REGISTER_DTE_ADDR);
if (!(0xCAFEB000 == ret)) {
- pr_info("error when %s.\n", __func__);
+ grf_value = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1);
+ pr_info("error when %s. grf = 0x%08x\n", __func__, grf_value);
return false;
}
}
return true;
}
}
+
if (IOMMU_REG_POLL_COUNT_FAST == i) {
pr_info("%s,Reset request failed, MMU status is 0x%08X\n",
__func__, __raw_readl(base + IOMMU_REGISTER_DTE_ADDR));
return true;
}
-static void __iommu_set_ptbase(void __iomem *base, unsigned long pgd)
+static void rockchip_iommu_set_ptbase(void __iomem *base, unsigned long pgd)
{
__raw_writel(pgd, base + IOMMU_REGISTER_DTE_ADDR);
}
-static bool iommu_reset(void __iomem *base, const char *dbgname)
+static bool rockchip_iommu_reset(void __iomem *base, const char *dbgname)
{
- bool err = true;
+ bool ret = true;
- err = iommu_enable_stall(base);
- if (!err) {
- pr_info("%s:stall failed: %s\n", __func__, dbgname);
- return err;
+ ret = rockchip_iommu_raw_reset(base);
+ if (!ret) {
+ pr_info("(%s), %s failed\n", dbgname, __func__);
+ return ret;
}
- err = iommu_raw_reset(base);
- if (err) {
- if (base != rk312x_vop_mmu_base)
- __raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
+
+ if (base != rk312x_vop_mmu_base)
+ __raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
IOMMU_INTERRUPT_READ_BUS_ERROR,
- base+IOMMU_REGISTER_INT_MASK);
- else
- __raw_writel(0x00, base + IOMMU_REGISTER_INT_MASK);
- }
- iommu_disable_stall(base);
- if (!err)
- pr_info("%s: failed: %s\n", __func__, dbgname);
- return err;
+ base + IOMMU_REGISTER_INT_MASK);
+ else
+ __raw_writel(0x00, base + IOMMU_REGISTER_INT_MASK);
+
+ return ret;
}
-static inline void pgtable_flush(void *vastart, void *vaend)
+static inline void rockchip_pgtable_flush(void *vastart, void *vaend)
{
#ifdef CONFIG_ARM
dmac_flush_range(vastart, vaend);
#endif
}
-static void set_fault_handler(struct iommu_drvdata *data,
- rockchip_iommu_fault_handler_t handler)
+static void dump_pagetbl(dma_addr_t fault_address, u32 addr_dte)
{
- unsigned long flags;
-
- write_lock_irqsave(&data->lock, flags);
- data->fault_handler = handler;
- write_unlock_irqrestore(&data->lock, flags);
+ u32 dte_index, pte_index, page_offset;
+ u32 mmu_dte_addr;
+ phys_addr_t mmu_dte_addr_phys, dte_addr_phys;
+ u32 *dte_addr;
+ u32 dte;
+ phys_addr_t pte_addr_phys = 0;
+ u32 *pte_addr = NULL;
+ u32 pte = 0;
+ phys_addr_t page_addr_phys = 0;
+ u32 page_flags = 0;
+
+ dte_index = rockchip_lv1ent_offset(fault_address);
+ pte_index = rockchip_lv2ent_offset(fault_address);
+ page_offset = (u32)(fault_address & 0x00000fff);
+
+ mmu_dte_addr = addr_dte;
+ mmu_dte_addr_phys = (phys_addr_t)mmu_dte_addr;
+
+ dte_addr_phys = mmu_dte_addr_phys + (4 * dte_index);
+ dte_addr = phys_to_virt(dte_addr_phys);
+ dte = *dte_addr;
+
+ if (!(IOMMU_FLAGS_PRESENT & dte))
+ goto print_it;
+
+ pte_addr_phys = ((phys_addr_t)dte & 0xfffff000) + (pte_index * 4);
+ pte_addr = phys_to_virt(pte_addr_phys);
+ pte = *pte_addr;
+
+ if (!(IOMMU_FLAGS_PRESENT & pte))
+ goto print_it;
+
+ page_addr_phys = ((phys_addr_t)pte & 0xfffff000) + page_offset;
+ page_flags = pte & 0x000001fe;
+
+print_it:
+ pr_err("iova = %pad: dte_index: 0x%03x pte_index: 0x%03x page_offset: 0x%03x\n",
+ &fault_address, dte_index, pte_index, page_offset);
+ pr_err("mmu_dte_addr: %pa dte@%pa: %#08x valid: %u pte@%pa: %#08x valid: %u page@%pa flags: %#03x\n",
+ &mmu_dte_addr_phys, &dte_addr_phys, dte,
+ (dte & IOMMU_FLAGS_PRESENT), &pte_addr_phys, pte,
+ (pte & IOMMU_FLAGS_PRESENT), &page_addr_phys, page_flags);
}
-static int default_fault_handler(struct device *dev,
- enum rk_iommu_inttype itype,
- unsigned long pgtable_base,
- unsigned long fault_addr,
- unsigned int status)
+static irqreturn_t rockchip_iommu_irq(int irq, void *dev_id)
{
- struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+ /* SYSMMU is in blocked when interrupt occurred. */
+ struct iommu_drvdata *data = dev_id;
+ u32 status;
+ u32 rawstat;
+ dma_addr_t fault_address;
+ int i;
+ unsigned long flags;
+ int ret;
+ u32 reg_status;
- if (!data) {
- dev_err(dev->archdata.iommu,"%s,iommu device not assigned yet\n", __func__);
- return 0;
+ spin_lock_irqsave(&data->data_lock, flags);
+
+ if (!rockchip_is_iommu_active(data)) {
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ return IRQ_HANDLED;
}
- if ((itype >= IOMMU_FAULTS_NUM) || (itype < IOMMU_PAGEFAULT))
- itype = IOMMU_FAULT_UNKNOWN;
- if (itype == IOMMU_BUSERROR)
- dev_err(dev->archdata.iommu,"%s occured at 0x%lx(Page table base: 0x%lx)\n",
- iommu_fault_name[itype], fault_addr, pgtable_base);
+ for (i = 0; i < data->num_res_mem; i++) {
+ status = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_INT_STATUS);
+ if (status == 0)
+ continue;
- if (itype == IOMMU_PAGEFAULT)
- dev_err(dev->archdata.iommu,"IOMMU:Page fault detected at 0x%lx from bus id %d of type %s on %s\n",
- fault_addr,
- (status >> 6) & 0x1F,
- (status & 32) ? "write" : "read",
- data->dbgname);
+ rawstat = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_INT_RAWSTAT);
- dev_err(dev->archdata.iommu,"Generating Kernel OOPS... because it is unrecoverable.\n");
+ reg_status = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_STATUS);
- BUG();
+ dev_info(data->iommu, "1.rawstat = 0x%08x,status = 0x%08x,reg_status = 0x%08x\n",
+ rawstat, status, reg_status);
- return 0;
-}
+ if (rawstat & IOMMU_INTERRUPT_PAGE_FAULT) {
+ u32 dte;
+ int flags;
-static void dump_pagetbl(u32 fault_address, u32 addr_dte)
-{
- u32 lv1_offset;
- u32 lv2_offset;
-
- u32 *lv1_entry_pa;
- u32 *lv1_entry_va;
- u32 *lv1_entry_value;
-
- u32 *lv2_base;
- u32 *lv2_entry_pa;
- u32 *lv2_entry_va;
- u32 *lv2_entry_value;
-
-
- lv1_offset = lv1ent_offset(fault_address);
- lv2_offset = lv2ent_offset(fault_address);
-
- lv1_entry_pa = (u32 *)addr_dte + lv1_offset;
- lv1_entry_va = (u32 *)(__va(addr_dte)) + lv1_offset;
- lv1_entry_value = (u32 *)(*lv1_entry_va);
-
- lv2_base = (u32 *)((*lv1_entry_va) & 0xfffffffe);
- lv2_entry_pa = (u32 *)lv2_base + lv2_offset;
- lv2_entry_va = (u32 *)(__va(lv2_base)) + lv2_offset;
- lv2_entry_value = (u32 *)(*lv2_entry_va);
-
- dev_info(NULL,"fault address = 0x%08x,dte addr pa = 0x%08x,va = 0x%08x\n",
- fault_address, addr_dte, (u32)__va(addr_dte));
- dev_info(NULL,"lv1_offset = 0x%x,lv1_entry_pa = 0x%08x,lv1_entry_va = 0x%08x\n",
- lv1_offset, (u32)lv1_entry_pa, (u32)lv1_entry_va);
- dev_info(NULL,"lv1_entry_value(*lv1_entry_va) = 0x%08x,lv2_base = 0x%08x\n",
- (u32)lv1_entry_value, (u32)lv2_base);
- dev_info(NULL,"lv2_offset = 0x%x,lv2_entry_pa = 0x%08x,lv2_entry_va = 0x%08x\n",
- lv2_offset, (u32)lv2_entry_pa, (u32)lv2_entry_va);
- dev_info(NULL,"lv2_entry value(*lv2_entry_va) = 0x%08x\n",
- (u32)lv2_entry_value);
-}
+ fault_address = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_PAGE_FAULT_ADDR);
-static irqreturn_t rockchip_iommu_irq(int irq, void *dev_id)
-{
- /* SYSMMU is in blocked when interrupt occurred. */
- struct iommu_drvdata *data = dev_id;
- struct resource *irqres;
- struct platform_device *pdev;
- enum rk_iommu_inttype itype = IOMMU_FAULT_UNKNOWN;
- u32 status;
- u32 rawstat;
- u32 int_status;
- u32 fault_address;
- int i, ret = 0;
+ dte = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_DTE_ADDR);
- read_lock(&data->lock);
+ flags = (status & 32) ? 1 : 0;
- if (!is_iommu_active(data)) {
- read_unlock(&data->lock);
- return IRQ_HANDLED;
- }
-
- if(cpu_is_rk312x() || cpu_is_rk3036())
- rockchip_vcodec_select(data->dbgname);
-
- pdev = to_platform_device(data->iommu);
+ dev_err(data->iommu, "Page fault detected at %pad from bus id %d of type %s on %s\n",
+ &fault_address, (status >> 6) & 0x1F,
+ (flags == 1) ? "write" : "read", data->dbgname);
- for (i = 0; i < data->num_res_irq; i++) {
- irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i);
- if (irqres && ((int)irqres->start == irq)) {
- if (data->res_bases[i] == rk312x_vop_mmu_base) {
- read_unlock(&data->lock);
- return IRQ_HANDLED;
- }
- break;
+ dump_pagetbl(fault_address, dte);
+
+ if (data->domain)
+ report_iommu_fault(data->domain, data->iommu,
+ fault_address, flags);
+
+ rockchip_iommu_page_fault_done(data->res_bases[i],
+ data->dbgname);
}
- }
- if (i == data->num_res_irq) {
- itype = IOMMU_FAULT_UNKNOWN;
- } else {
- int_status = __raw_readl(data->res_bases[i] +
- IOMMU_REGISTER_INT_STATUS);
-
- if (int_status != 0) {
- /*mask status*/
- __raw_writel(0x00, data->res_bases[i] +
- IOMMU_REGISTER_INT_MASK);
-
- rawstat = __raw_readl(data->res_bases[i] +
- IOMMU_REGISTER_INT_RAWSTAT);
-
- if (rawstat & IOMMU_INTERRUPT_PAGE_FAULT) {
- fault_address = __raw_readl(data->res_bases[i] +
- IOMMU_REGISTER_PAGE_FAULT_ADDR);
- itype = IOMMU_PAGEFAULT;
- } else if (rawstat & IOMMU_INTERRUPT_READ_BUS_ERROR) {
- itype = IOMMU_BUSERROR;
- } else {
- goto out;
- }
- dump_pagetbl(fault_address,
- __raw_readl(data->res_bases[i] +
- IOMMU_REGISTER_DTE_ADDR));
- } else {
- goto out;
+ if (rawstat & IOMMU_INTERRUPT_READ_BUS_ERROR) {
+ dev_err(data->iommu, "bus error occured at %pad\n",
+ &fault_address);
}
- }
- if (data->fault_handler) {
- unsigned long base = __raw_readl(data->res_bases[i] +
- IOMMU_REGISTER_DTE_ADDR);
+ if (rawstat & ~(IOMMU_INTERRUPT_READ_BUS_ERROR |
+ IOMMU_INTERRUPT_PAGE_FAULT)) {
+ dev_err(data->iommu, "unexpected int_status: %#08x\n\n",
+ rawstat);
+ }
+
+ __raw_writel(rawstat, data->res_bases[i] +
+ IOMMU_REGISTER_INT_CLEAR);
+
status = __raw_readl(data->res_bases[i] +
- IOMMU_REGISTER_STATUS);
- ret = data->fault_handler(data->dev, itype, base,
- fault_address, status);
- }
+ IOMMU_REGISTER_INT_STATUS);
- if (!ret && (itype != IOMMU_FAULT_UNKNOWN)) {
- if (IOMMU_PAGEFAULT == itype) {
- iommu_zap_tlb(data->res_bases[i]);
- iommu_page_fault_done(data->res_bases[i],
- data->dbgname);
- __raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
- IOMMU_INTERRUPT_READ_BUS_ERROR,
- data->res_bases[i] +
- IOMMU_REGISTER_INT_MASK);
- }
- } else {
- dev_err(data->iommu,"(%s) %s is not handled.\n",
- data->dbgname, iommu_fault_name[itype]);
- }
+ rawstat = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_INT_RAWSTAT);
+
+ reg_status = __raw_readl(data->res_bases[i] +
+ IOMMU_REGISTER_STATUS);
-out:
- read_unlock(&data->lock);
+ dev_info(data->iommu, "2.rawstat = 0x%08x,status = 0x%08x,reg_status = 0x%08x\n",
+ rawstat, status, reg_status);
+ ret = rockchip_iommu_zap_tlb_without_stall(data->res_bases[i]);
+ if (ret)
+ dev_err(data->iommu, "(%s) %s failed\n", data->dbgname,
+ __func__);
+ }
+
+ spin_unlock_irqrestore(&data->data_lock, flags);
return IRQ_HANDLED;
}
-static bool __rockchip_iommu_disable(struct iommu_drvdata *data)
+static bool rockchip_iommu_disable(struct iommu_drvdata *data)
{
unsigned long flags;
int i;
- bool disabled = false;
+ bool ret = false;
+
+ spin_lock_irqsave(&data->data_lock, flags);
+
+ if (!rockchip_set_iommu_inactive(data)) {
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ dev_info(data->iommu,"(%s) %d times left to be disabled\n",
+ data->dbgname, data->activations);
+ return ret;
+ }
- write_lock_irqsave(&data->lock, flags);
+ for (i = 0; i < data->num_res_mem; i++) {
+ ret = rockchip_iommu_enable_stall(data->res_bases[i]);
+ if (!ret) {
+ dev_info(data->iommu, "(%s), %s failed\n",
+ data->dbgname, __func__);
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ return false;
+ }
- if (!set_iommu_inactive(data))
- goto finish;
+ __raw_writel(0, data->res_bases[i] + IOMMU_REGISTER_INT_MASK);
- for (i = 0; i < data->num_res_mem; i++)
- iommu_disable_paging(data->res_bases[i]);
+ ret = rockchip_iommu_disable_paging(data->res_bases[i]);
+ if (!ret) {
+ rockchip_iommu_disable_stall(data->res_bases[i]);
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ dev_info(data->iommu, "%s error\n", __func__);
+ return ret;
+ }
+ rockchip_iommu_disable_stall(data->res_bases[i]);
+ }
- disabled = true;
data->pgtable = 0;
- data->domain = NULL;
-finish:
- write_unlock_irqrestore(&data->lock, flags);
- if (disabled)
- dev_info(data->iommu,"(%s) Disabled\n", data->dbgname);
- else
- dev_info(data->iommu,"(%s) %d times left to be disabled\n",
- data->dbgname, data->activations);
+ spin_unlock_irqrestore(&data->data_lock, flags);
+
+ dev_info(data->iommu,"(%s) Disabled\n", data->dbgname);
- return disabled;
+ return ret;
}
/* __rk_sysmmu_enable: Enables System MMU
* 0 if the System MMU has been just enabled and 1 if System MMU was already
* enabled before.
*/
-static int __rockchip_iommu_enable(struct iommu_drvdata *data,
- unsigned long pgtable,
- struct iommu_domain *domain)
+static int rockchip_iommu_enable(struct iommu_drvdata *data, unsigned long pgtable)
{
int i, ret = 0;
unsigned long flags;
- write_lock_irqsave(&data->lock, flags);
+ spin_lock_irqsave(&data->data_lock, flags);
- if (!set_iommu_active(data)) {
+ if (!rockchip_set_iommu_active(data)) {
if (WARN_ON(pgtable != data->pgtable)) {
ret = -EBUSY;
- set_iommu_inactive(data);
+ rockchip_set_iommu_inactive(data);
} else {
ret = 1;
}
- dev_info(data->iommu,"(%s) Already enabled\n", data->dbgname);
- goto finish;
- }
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ dev_info(data->iommu, "(%s) Already enabled\n", data->dbgname);
- data->pgtable = pgtable;
+ return ret;
+ }
for (i = 0; i < data->num_res_mem; i++) {
- bool status;
-
- status = iommu_enable_stall(data->res_bases[i]);
- if (status) {
- __iommu_set_ptbase(data->res_bases[i], pgtable);
- __raw_writel(IOMMU_COMMAND_ZAP_CACHE,
- data->res_bases[i] +
- IOMMU_REGISTER_COMMAND);
+ ret = rockchip_iommu_enable_stall(data->res_bases[i]);
+ if (!ret) {
+ dev_info(data->iommu, "(%s), %s failed\n",
+ data->dbgname, __func__);
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ return -EBUSY;
}
+
+ if (!strstr(data->dbgname, "isp")) {
+ if (!rockchip_iommu_reset(data->res_bases[i],
+ data->dbgname)) {
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ return -ENOENT;
+ }
+ }
+
+ rockchip_iommu_set_ptbase(data->res_bases[i], pgtable);
+
+ __raw_writel(IOMMU_COMMAND_ZAP_CACHE, data->res_bases[i] +
+ IOMMU_REGISTER_COMMAND);
+
__raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
IOMMU_INTERRUPT_READ_BUS_ERROR,
- data->res_bases[i]+IOMMU_REGISTER_INT_MASK);
- iommu_enable_paging(data->res_bases[i]);
- iommu_disable_stall(data->res_bases[i]);
+ data->res_bases[i] + IOMMU_REGISTER_INT_MASK);
+
+ ret = rockchip_iommu_enable_paging(data->res_bases[i]);
+ if (!ret) {
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ dev_info(data->iommu, "(%s), %s failed\n",
+ data->dbgname, __func__);
+ return -EBUSY;
+ }
+
+ rockchip_iommu_disable_stall(data->res_bases[i]);
}
- data->domain = domain;
+ data->pgtable = pgtable;
dev_info(data->iommu,"(%s) Enabled\n", data->dbgname);
-finish:
- write_unlock_irqrestore(&data->lock, flags);
-
- return ret;
-}
-bool rockchip_iommu_disable(struct device *dev)
-{
- struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
- bool disabled;
+ spin_unlock_irqrestore(&data->data_lock, flags);
- disabled = __rockchip_iommu_disable(data);
-
- return disabled;
+ return 0;
}
-void rockchip_iommu_tlb_invalidate(struct device *dev)
+int rockchip_iommu_tlb_invalidate(struct device *dev)
{
unsigned long flags;
struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
- read_lock_irqsave(&data->lock, flags);
-
- if(cpu_is_rk312x() || cpu_is_rk3036())
- rockchip_vcodec_select(data->dbgname);
-
- if (is_iommu_active(data)) {
+ spin_lock_irqsave(&data->data_lock, flags);
+
+ if (rockchip_is_iommu_active(data)) {
int i;
+ int ret;
for (i = 0; i < data->num_res_mem; i++) {
- if (!iommu_zap_tlb(data->res_bases[i]))
- dev_err(dev->archdata.iommu,"%s,invalidating TLB failed\n",
- data->dbgname);
+ ret = rockchip_iommu_zap_tlb_without_stall(data->res_bases[i]);
+ if (ret) {
+ dev_err(dev->archdata.iommu, "(%s) %s failed\n",
+ data->dbgname, __func__);
+ spin_unlock_irqrestore(&data->data_lock, flags);
+ return ret;
+ }
+
}
} else {
- dev_dbg(dev->archdata.iommu,"(%s) Disabled. Skipping invalidating TLB.\n",
+ dev_dbg(dev->archdata.iommu, "(%s) Disabled. Skipping invalidating TLB.\n",
data->dbgname);
}
- read_unlock_irqrestore(&data->lock, flags);
+ spin_unlock_irqrestore(&data->data_lock, flags);
+
+ return 0;
}
static phys_addr_t rockchip_iommu_iova_to_phys(struct iommu_domain *domain,
spin_lock_irqsave(&priv->pgtablelock, flags);
- entry = section_entry(priv->pgtable, iova);
- entry = page_entry(entry, iova);
- phys = spage_phys(entry) + spage_offs(iova);
+ entry = rockchip_section_entry(priv->pgtable, iova);
+ entry = rockchip_page_entry(entry, iova);
+ phys = rockchip_spage_phys(entry) + rockchip_spage_offs(iova);
spin_unlock_irqrestore(&priv->pgtablelock, flags);
return phys;
}
-static int lv2set_page(unsigned long *pent, phys_addr_t paddr,
+static int rockchip_lv2set_page(unsigned long *pent, phys_addr_t paddr,
size_t size, short *pgcnt)
{
- if (!lv2ent_fault(pent))
+ if (!rockchip_lv2ent_fault(pent))
return -EADDRINUSE;
- *pent = mk_lv2ent_spage(paddr);
- pgtable_flush(pent, pent + 1);
+ *pent = rockchip_mk_lv2ent_spage(paddr);
+ rockchip_pgtable_flush(pent, pent + 1);
*pgcnt -= 1;
return 0;
}
-static unsigned long *alloc_lv2entry(unsigned long *sent,
+static unsigned long *rockchip_alloc_lv2entry(unsigned long *sent,
unsigned long iova, short *pgcounter)
{
- if (lv1ent_fault(sent)) {
+ if (rockchip_lv1ent_fault(sent)) {
unsigned long *pent;
pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC);
if (!pent)
return NULL;
- *sent = mk_lv1ent_page(__pa(pent));
+ *sent = rockchip_mk_lv1ent_page(__pa(pent));
kmemleak_ignore(pent);
*pgcounter = NUM_LV2ENTRIES;
- pgtable_flush(pent, pent + NUM_LV2ENTRIES);
- pgtable_flush(sent, sent + 1);
+ rockchip_pgtable_flush(pent, pent + NUM_LV2ENTRIES);
+ rockchip_pgtable_flush(sent, sent + 1);
}
- return page_entry(sent, iova);
+ return rockchip_page_entry(sent, iova);
}
static size_t rockchip_iommu_unmap(struct iommu_domain *domain,
spin_lock_irqsave(&priv->pgtablelock, flags);
- ent = section_entry(priv->pgtable, iova);
+ ent = rockchip_section_entry(priv->pgtable, iova);
- if (unlikely(lv1ent_fault(ent))) {
+ if (unlikely(rockchip_lv1ent_fault(ent))) {
if (size > SPAGE_SIZE)
size = SPAGE_SIZE;
goto done;
/* lv1ent_page(sent) == true here */
- ent = page_entry(ent, iova);
+ ent = rockchip_page_entry(ent, iova);
- if (unlikely(lv2ent_fault(ent))) {
+ if (unlikely(rockchip_lv2ent_fault(ent))) {
size = SPAGE_SIZE;
goto done;
}
*ent = 0;
size = SPAGE_SIZE;
- priv->lv2entcnt[lv1ent_offset(iova)] += 1;
+ priv->lv2entcnt[rockchip_lv1ent_offset(iova)] += 1;
goto done;
done:
spin_lock_irqsave(&priv->pgtablelock, flags);
- entry = section_entry(priv->pgtable, iova);
+ entry = rockchip_section_entry(priv->pgtable, iova);
- pent = alloc_lv2entry(entry, iova,
- &priv->lv2entcnt[lv1ent_offset(iova)]);
+ pent = rockchip_alloc_lv2entry(entry, iova,
+ &priv->lv2entcnt[rockchip_lv1ent_offset(iova)]);
if (!pent)
ret = -ENOMEM;
else
- ret = lv2set_page(pent, paddr, size,
- &priv->lv2entcnt[lv1ent_offset(iova)]);
+ ret = rockchip_lv2set_page(pent, paddr, size,
+ &priv->lv2entcnt[rockchip_lv1ent_offset(iova)]);
if (ret) {
pr_info("%s: Failed to map iova 0x%lx/0x%x bytes\n", __func__,
return ret;
}
-static void rockchip_iommu_detach_device(struct iommu_domain *domain,
- struct device *dev)
+static void rockchip_iommu_detach_device(struct iommu_domain *domain, struct device *dev)
{
struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
struct rk_iommu_domain *priv = domain->priv;
spin_lock_irqsave(&priv->lock, flags);
- list_for_each(pos, &priv->clients)
- {
+ list_for_each(pos, &priv->clients) {
if (list_entry(pos, struct iommu_drvdata, node) == data) {
found = true;
break;
}
}
- if (!found)
- goto finish;
-
- if(cpu_is_rk312x() || cpu_is_rk3036())
- rockchip_vcodec_select(data->dbgname);
-
- if (__rockchip_iommu_disable(data)) {
- dev_info(dev->archdata.iommu,"%s: Detached IOMMU with pgtable %#lx\n",
+
+ if (!found) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return;
+ }
+
+ if (rockchip_iommu_disable(data)) {
+ dev_dbg(dev->archdata.iommu,"%s: Detached IOMMU with pgtable %#lx\n",
__func__, __pa(priv->pgtable));
- list_del(&data->node);
- INIT_LIST_HEAD(&data->node);
+ data->domain = NULL;
+ list_del_init(&data->node);
} else
- dev_info(dev->archdata.iommu,"%s: Detaching IOMMU with pgtable %#lx delayed",
+ dev_err(dev->archdata.iommu,"%s: Detaching IOMMU with pgtable %#lx delayed",
__func__, __pa(priv->pgtable));
-finish:
spin_unlock_irqrestore(&priv->lock, flags);
}
-static int rockchip_iommu_attach_device(struct iommu_domain *domain,
- struct device *dev)
+static int rockchip_iommu_attach_device(struct iommu_domain *domain, struct device *dev)
{
struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
struct rk_iommu_domain *priv = domain->priv;
spin_lock_irqsave(&priv->lock, flags);
- if(cpu_is_rk312x() || cpu_is_rk3036())
- rockchip_vcodec_select(data->dbgname);
-
- ret = __rockchip_iommu_enable(data, __pa(priv->pgtable), domain);
+ ret = rockchip_iommu_enable(data, __pa(priv->pgtable));
if (ret == 0) {
/* 'data->node' must not be appeared in priv->clients */
BUG_ON(!list_empty(&data->node));
- data->dev = dev;
list_add_tail(&data->node, &priv->clients);
+ data->domain = domain;
}
spin_unlock_irqrestore(&priv->lock, flags);
static void rockchip_iommu_domain_destroy(struct iommu_domain *domain)
{
struct rk_iommu_domain *priv = domain->priv;
- struct iommu_drvdata *data;
- unsigned long flags;
int i;
WARN_ON(!list_empty(&priv->clients));
- spin_lock_irqsave(&priv->lock, flags);
-
- list_for_each_entry(data, &priv->clients, node) {
- if(cpu_is_rk312x() || cpu_is_rk3036())
- rockchip_vcodec_select(data->dbgname);
- while (!rockchip_iommu_disable(data->dev))
- ; /* until System MMU is actually disabled */
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
for (i = 0; i < NUM_LV1ENTRIES; i++)
- if (lv1ent_page(priv->pgtable + i))
+ if (rockchip_lv1ent_page(priv->pgtable + i))
kmem_cache_free(lv2table_kmem_cache,
- __va(lv2table_base(priv->pgtable + i)));
+ __va(rockchip_lv2table_base(priv->pgtable + i)));
free_pages((unsigned long)priv->pgtable, 0);
free_pages((unsigned long)priv->lv2entcnt, 0);
if (!priv->lv2entcnt)
goto err_counter;
- pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES);
+ rockchip_pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES);
spin_lock_init(&priv->lock);
spin_lock_init(&priv->pgtablelock);
.pgsize_bitmap = SPAGE_SIZE,
};
-static int rockchip_iommu_prepare(void)
-{
- int ret = 0;
- static int registed;
-
- if (registed)
- return 0;
-
- lv2table_kmem_cache = kmem_cache_create("rk-iommu-lv2table",
- LV2TABLE_SIZE,
- LV2TABLE_SIZE,
- 0, NULL);
- if (!lv2table_kmem_cache) {
- pr_info("%s: failed to create kmem cache\n", __func__);
- return -ENOMEM;
- }
- ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
- if (!ret)
- registed = 1;
- else
- pr_info("%s:failed to set iommu to bus\r\n", __func__);
- return ret;
-}
-
static int rockchip_get_iommu_resource_num(struct platform_device *pdev,
unsigned int type)
{
int num = 0;
int i;
-#if 0
- pr_info("dev num_resources %d type = 0x%08x\n",pdev->num_resources, type);
-#endif
+
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];
-#if 0
-dev_info(&pdev->dev, "r[%d] start %08x end %08x flags %08lx name (%s) resource_type %08lx\n", i, r->start, r->end, r->flags, r->name, resource_type(r));
-#endif
if (type == resource_type(r))
num++;
}
return num;
}
-static struct kobject *dump_mmu_object;
-
-static int dump_mmu_pagetbl(struct device *dev, struct device_attribute *attr,
- const char *buf, u32 count)
-{
- u32 fault_address;
- u32 iommu_dte;
- u32 mmu_base;
- void __iomem *base;
- u32 ret;
-
- ret = kstrtouint(buf, 0, &mmu_base);
- if (ret)
- dev_dbg(dev,"%s is not in hexdecimal form.\n", buf);
- base = ioremap(mmu_base, 0x100);
- if (base != rk312x_vop_mmu_base) {
- iommu_dte = __raw_readl(base + IOMMU_REGISTER_DTE_ADDR);
- fault_address = __raw_readl(base + IOMMU_REGISTER_PAGE_FAULT_ADDR);
- dump_pagetbl(fault_address, iommu_dte);
- } else {
- dev_dbg(dev,"vop mmu not support\n");
- }
- return count;
-}
-
-static DEVICE_ATTR(dump_mmu_pgtable, 0644, NULL, dump_mmu_pagetbl);
-
-void dump_iommu_sysfs_init(void)
-{
- u32 ret;
-
- dump_mmu_object = kobject_create_and_add("rk_iommu", NULL);
- if (dump_mmu_object == NULL)
- return;
- ret = sysfs_create_file(dump_mmu_object,
- &dev_attr_dump_mmu_pgtable.attr);
-}
-
static int rockchip_iommu_probe(struct platform_device *pdev)
{
int i, ret;
struct iommu_drvdata *data;
dev = &pdev->dev;
-
-#if 0
-struct resource *res = pdev->resource;
-
-for (i = 0; i < pdev->num_resources; i++, res++) {
- pr_info("r[%d] start %08x end %08x flags %08lx name (%s) resource_type %08lx\n", i, res->start, res->end, res->flags, res->name, resource_type(res));
-}
-#endif
- ret = rockchip_iommu_prepare();
- if (ret) {
- dev_err(dev,"%s,failed\r\n", __func__);
- goto err_alloc;
- }
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_dbg(dev, "Not enough memory\n");
- ret = -ENOMEM;
- goto err_alloc;
+ return -ENOMEM;
}
+
dev_set_drvdata(dev, data);
-/*
- ret = dev_set_drvdata(dev, data);
- if (ret)
- {
- dev_dbg(dev, "Unabled to initialize driver data\n");
- goto err_init;
- }
-*/
- if (pdev->dev.of_node) {
- of_property_read_string(pdev->dev.of_node,
- "dbgname", &(data->dbgname));
- } else {
- dev_dbg(dev,
- "dbgname not assigned in device tree or device node not exist\r\n");
- }
+
+ if (pdev->dev.of_node)
+ of_property_read_string(pdev->dev.of_node, "dbgname",
+ &(data->dbgname));
+ else
+ dev_dbg(dev, "dbgname not assigned in device tree or device node not exist\r\n");
dev_info(dev,"(%s) Enter\n", data->dbgname);
-
data->num_res_mem = rockchip_get_iommu_resource_num(pdev,
IORESOURCE_MEM);
if (0 == data->num_res_mem) {
dev_err(dev,"can't find iommu memory resource \r\n");
- goto err_init;
+ return -ENOMEM;
}
dev_dbg(dev,"data->num_res_mem=%d\n", data->num_res_mem);
+
data->num_res_irq = rockchip_get_iommu_resource_num(pdev,
IORESOURCE_IRQ);
if (0 == data->num_res_irq) {
dev_err(dev,"can't find iommu irq resource \r\n");
- goto err_init;
+ return -ENOMEM;
}
dev_dbg(dev,"data->num_res_irq=%d\n", data->num_res_irq);
sizeof(*data->res_bases), GFP_KERNEL);
if (data->res_bases == NULL) {
dev_err(dev, "Not enough memory\n");
- ret = -ENOMEM;
- goto err_init;
+ return -ENOMEM;
}
for (i = 0; i < data->num_res_mem; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res) {
dev_err(dev,"Unable to find IOMEM region\n");
- ret = -ENOENT;
- goto err_res;
+ return -ENOENT;
}
- data->res_bases[i] = devm_ioremap(dev,res->start, resource_size(res));
- dev_dbg(dev,"res->start = 0x%08x ioremap to data->res_bases[%d] = 0x%08x\n",
- res->start, i, (unsigned int)data->res_bases[i]);
+
+ data->res_bases[i] = devm_ioremap(dev,res->start,
+ resource_size(res));
if (!data->res_bases[i]) {
- pr_err("Unable to map IOMEM @ PA:%#x\n", res->start);
- ret = -ENOENT;
- goto err_res;
+ dev_err(dev, "Unable to map IOMEM @ PA:%#x\n",
+ res->start);
+ return -ENOMEM;
}
- if (cpu_is_rk312x() || cpu_is_rk3036()) {
- rockchip_vcodec_select(data->dbgname);
- if (strstr(data->dbgname, "vop") && cpu_is_rk312x()) {
- rk312x_vop_mmu_base = data->res_bases[0];
- dev_dbg(dev,"rk312x_vop_mmu_base = 0x%08x\n",(unsigned int)rk312x_vop_mmu_base);
- }
- }
- if (!strstr(data->dbgname, "isp")) {
- if (!iommu_reset(data->res_bases[i], data->dbgname)) {
- ret = -ENOENT;
- goto err_res;
- }
+ dev_dbg(dev,"res->start = 0x%08x ioremap to data->res_bases[%d] = 0x%08x\n",
+ res->start, i, (unsigned int)data->res_bases[i]);
+
+ if (strstr(data->dbgname, "vop") && cpu_is_rk312x()) {
+ rk312x_vop_mmu_base = data->res_bases[0];
+ dev_dbg(dev, "rk312x_vop_mmu_base = 0x%08x\n",
+ (unsigned int)rk312x_vop_mmu_base);
}
}
for (i = 0; i < data->num_res_irq; i++) {
- ret = platform_get_irq(pdev, i);
- if (ret <= 0) {
- dev_err(dev,"Unable to find IRQ resource\n");
- goto err_irq;
- }
if (cpu_is_rk312x() && strstr(data->dbgname, "vop")) {
dev_info(dev, "skip request vop mmu irq\n");
continue;
}
+
+ ret = platform_get_irq(pdev, i);
+ if (ret <= 0) {
+ dev_err(dev,"Unable to find IRQ resource\n");
+ return -ENOENT;
+ }
+
ret = devm_request_irq(dev, ret, rockchip_iommu_irq,
IRQF_SHARED, dev_name(dev), data);
if (ret) {
- dev_err(dev,"Unabled to register interrupt handler\n");
- goto err_irq;
+ dev_err(dev, "Unabled to register interrupt handler\n");
+ return -ENOENT;
}
}
+
ret = rockchip_init_iovmm(dev, &data->vmm);
if (ret)
- goto err_irq;
+ return ret;
data->iommu = dev;
- rwlock_init(&data->lock);
+ spin_lock_init(&data->data_lock);
INIT_LIST_HEAD(&data->node);
- set_fault_handler(data, &default_fault_handler);
-
dev_info(dev,"(%s) Initialized\n", data->dbgname);
- return 0;
-err_irq:
-err_res:
-err_init:
-err_alloc:
- dev_err(dev, "Failed to initialize\n");
- return ret;
+ return 0;
}
#ifdef CONFIG_OF
static int __init rockchip_iommu_init_driver(void)
{
- dump_iommu_sysfs_init();
+ int ret;
+
+ lv2table_kmem_cache = kmem_cache_create("rk-iommu-lv2table",
+ LV2TABLE_SIZE, LV2TABLE_SIZE,
+ 0, NULL);
+ if (!lv2table_kmem_cache) {
+ pr_info("%s: failed to create kmem cache\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
+ if (ret)
+ return ret;
return platform_driver_register(&rk_iommu_driver);
}
struct iommu_drvdata {
struct list_head node; /* entry of rk_iommu_domain.clients */
struct device *iommu; /* IOMMU's device descriptor */
- struct device *dev; /* Owner of IOMMU */
int num_res_mem;
int num_res_irq;
const char *dbgname;
void __iomem **res_bases;
int activations;
- rwlock_t lock;
+ spinlock_t data_lock;
struct iommu_domain *domain; /* domain given to iommu_attach_device() */
- rockchip_iommu_fault_handler_t fault_handler;
unsigned long pgtable;
struct rk_iovmm vmm;
};
#ifdef CONFIG_ROCKCHIP_IOMMU
-/**
-* rockchip_iommu_disable() - disable iommu mmu of ip
-* @owner: The device whose IOMMU is about to be disabled.
-*
-* This function disable iommu to transfer address
- * from virtual address to physical address
- */
-bool rockchip_iommu_disable(struct device *owner);
-
/**
* rockchip_iommu_tlb_invalidate() - flush all TLB entry in iommu
* @owner: The device whose IOMMU.
*
* This function flush all TLB entry in iommu
*/
-void rockchip_iommu_tlb_invalidate(struct device *owner);
+int rockchip_iommu_tlb_invalidate(struct device *owner);
#else /* CONFIG_ROCKCHIP_IOMMU */
-static inline bool rockchip_iommu_disable(struct device *owner)
-{
- return false;
-}
-static inline void rockchip_iommu_tlb_invalidate(struct device *owner)
+static inline int rockchip_iommu_tlb_invalidate(struct device *owner)
{
- return false;
+ return -1;
}
#endif
void rockchip_iovmm_set_fault_handler(struct device *dev,
rockchip_iommu_fault_handler_t handler)
{
- unsigned long flags;
- struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
-
- write_lock_irqsave(&data->lock, flags);
- data->fault_handler = handler;
- write_unlock_irqrestore(&data->lock, flags);
+ return;
}
int rockchip_iovmm_activate(struct device *dev)
spin_unlock(&vmm->lock);
- rockchip_iommu_tlb_invalidate(dev);
- /*
- pr_err("IOVMM: Allocated VM region @ %#x/%#X bytes.\n",
+ ret = rockchip_iommu_tlb_invalidate(dev);
+ if (ret)
+ goto err_map_map;
+
+ dev_dbg(dev->archdata.iommu, "IOVMM: Allocated VM region @ %#x/%#X bytes.\n",
region->start, region->size);
- */
+
return region->start;
err_map_map:
err_map_noiomem:
kfree(region);
err_map_nomem:
- pr_err("IOVMM: Failed to allocated VM region for %#x bytes.\n", size);
+ dev_err(dev->archdata.iommu, "IOVMM: Failed to allocated VM region for %#x bytes.\n", size);
return (dma_addr_t)ret;
}
gen_pool_free(vmm->vmm_pool, region->start, region->size);
WARN_ON(unmapped_size != region->size);
- /*
- pr_err("IOVMM: Unmapped %#x bytes from %#x.\n",
+
+ dev_dbg(dev->archdata.iommu, "IOVMM: Unmapped %#x bytes from %#x.\n",
unmapped_size, region->start);
- */
+
kfree(region);
}
int ret;
if (WARN_ON((phys + size) >= IOVA_START)) {
- pr_err("Unable to create one to one mapping for %#x @ %#x\n",
+ dev_err(dev->archdata.iommu, "Unable to create one to one mapping for %#x @ %#x\n",
size, phys);
return -EINVAL;
}
spin_unlock(&vmm->lock);
- rockchip_iommu_tlb_invalidate(dev);
+ ret = rockchip_iommu_tlb_invalidate(dev);
+ if (ret)
+ return ret;
return 0;
}
spin_unlock(&vmm->lock);
unmapped_size = iommu_unmap(vmm->domain, region->start, region->size);
- rockchip_iommu_tlb_invalidate(dev);
WARN_ON(unmapped_size != region->size);
- pr_err("IOVMM: Unmapped %#x bytes from %#x.\n",
+ dev_dbg(dev->archdata.iommu, "IOVMM: Unmapped %#x bytes from %#x.\n",
unmapped_size, region->start);
kfree(region);
INIT_LIST_HEAD(&vmm->regions_list);
- pr_info("IOVMM: Created %#x B IOVMM from %#x.\n",
+ dev_info(iommu, "IOVMM: Created %#x B IOVMM from %#x.\n",
IOVM_SIZE, IOVA_START);
return 0;
err_setup_domain:
gen_pool_destroy(vmm->vmm_pool);
err_setup_genalloc:
- pr_err("IOVMM: Failed to create IOVMM (%d)\n", ret);
+ dev_err(iommu, "IOVMM: Failed to create IOVMM (%d)\n", ret);
return ret;
}
depends on ROCKCHIP_CAMERA_SENSOR_INTERFACE
default y
+ config RK30_CAMERA_PINGPONG
+ tristate "rk30_camera_pingpong"
+ depends on ROCKCHIP_CAMERA_SENSOR_INTERFACE
+
endmenu
+obj-$(CONFIG_RK30_CAMERA_PINGPONG) += rk30_camera_pingpong.o generic_sensor.o \\r
+gc0307.o \\r
+gc0308.o \\r
+gc0309.o \\r
+gc0328.o \\r
+gc0329.o \\r
+gc2015.o \\r
+gc2035.o \\r
+gt2005.o \\r
+hm2057.o \\r
+hm5065.o \\r
+mt9p111.o \\r
+nt99160_2way.o \\r
+nt99240_2way.o \\r
+ov2659.o \\r
+ov5640.o \\r
+sp0838.o \\r
+sp2518.o\r
obj-$(CONFIG_RK30_CAMERA_ONEFRAME) += rk30_camera_oneframe.o generic_sensor.o \\r
gc0307.o \\r
gc0308.o \\r
//struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
int value = ext_ctrl->value;\r
\r
+ \r
+ if(value == 0xfefe5a5a){ \r
+ if ((ctrl_info->cur_value == 2) || (ctrl_info->cur_value == 1)) {\r
+ generic_sensor_ioctrl(icd, Sensor_Flash, Flash_On); \r
+ }\r
+ \r
+ return 0;\r
+ }\r
if ((value < ctrl_info->qctrl->minimum) || (value > ctrl_info->qctrl->maximum)) {\r
printk(KERN_ERR "%s(%d): value(0x%x) isn't between in (0x%x,0x%x)\n",__FUNCTION__,__LINE__,value,\r
ctrl_info->qctrl->minimum,ctrl_info->qctrl->maximum);\r
/*********yzm**********/
static u32 CRU_PCLK_REG30;
+static u32 CRU_CLK_OUT;
+static u32 clk_cif_out_src_gate_en;
+static u32 CRU_CLKSEL29_CON;
+static u32 cif0_clk_sel;
static u32 ENANABLE_INVERT_PCLK_CIF0;
static u32 DISABLE_INVERT_PCLK_CIF0;
static u32 ENANABLE_INVERT_PCLK_CIF1;
static u32 DISABLE_INVERT_PCLK_CIF1;
-
+static u32 CHIP_NAME;
+
#define write_cru_reg(addr, val) __raw_writel(val, addr+RK_CRU_VIRT)
#define read_cru_reg(addr) __raw_readl(addr+RK_CRU_VIRT)
#define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
1. Add power and powerdown controled by PMU.
*v0.1.8:
1. Support front and rear camera support are the same.
+*v0.1.9:
+ 1. Support pingpong mode.
+ 2. Fix cif_clk_out cannot close which base on XIN24M and cannot turn to 0
+ 3. Move Camera Sensor Macro from rk_camera.h to rk_camera_sensor_info.h
+ 4. Support flash control when preview size == picture size
*/
-#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0x8)
+#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0x9)
static int version = RK_CAM_VERSION_CODE;
module_param(version, int, S_IRUGO);
DISABLE_INVERT_PCLK_CIF0 = ((0x1<<23)|(0x0<<7));
ENANABLE_INVERT_PCLK_CIF1 = ENANABLE_INVERT_PCLK_CIF0;
DISABLE_INVERT_PCLK_CIF1 = DISABLE_INVERT_PCLK_CIF0;
+
+ CRU_CLK_OUT = 0xdc;
+ clk_cif_out_src_gate_en = ((0x1<<23)|(0x1<<7));
+ CRU_CLKSEL29_CON = 0xb8;
+ cif0_clk_sel = ((0x1<<23)|(0x0<<7));
+
+ CHIP_NAME = 3126;
}
}
static inline void rk_cru_set_soft_reset(u32 idx, bool on , u32 RK_CRU_SOFTRST_CON)
int bytes_per_line_host;
fmt.packing = SOC_MBUS_PACKING_1_5X8;
- debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
{
int err = 0,cif;
struct rk_cif_clk *clk;
- struct clk *cif_clk_out_div;
debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
clk_set_rate(clk->cif_clk_out,clk_rate);
clk->on = true;
} else if (!on && clk->on) {
+ clk_set_rate(clk->cif_clk_out,36000000);/*yzm :just for close clk which base on XIN24M */
msleep(100);
clk_disable_unprepare(clk->aclk_cif);
clk_disable_unprepare(clk->hclk_cif);
clk_disable_unprepare(clk->cif_clk_in);
+ if(CHIP_NAME == 3126){
+ write_cru_reg(CRU_CLKSEL29_CON, 0x007c0000);
+ write_cru_reg(CRU_CLK_OUT, 0x00800080);
+ }
clk_disable_unprepare(clk->cif_clk_out);
clk_disable_unprepare(clk->pd_cif);
- clk->on = false;
- if(cif){
- cif_clk_out_div = clk_get(NULL, "cif1_out_div");
- }else{
- cif_clk_out_div = clk_get(NULL, "cif0_out_div");
- if(IS_ERR_OR_NULL(cif_clk_out_div)) {
- cif_clk_out_div = clk_get(NULL, "cif_out_div");
- }
- }
-
- if(!IS_ERR_OR_NULL(cif_clk_out_div)) { /* ddl@rock-chips.com: v0.3.0x13 */
- err = clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
- clk_put(cif_clk_out_div);
- } else {
- err = -1;
- }
-
- if(err)
- RKCAMERA_TR("WARNING %s_%s_%d: camera sensor mclk maybe not close, please check!!!\n", __FILE__, __FUNCTION__, __LINE__);
+
+ clk->on = false;
}
//spin_unlock(&clk->lock);
rk_camera_clk_ctrl_end:
}
} else {
if(IS_CIF0()){
- write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
+ write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFFF7F ) | DISABLE_INVERT_PCLK_CIF0);
} else {
write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
}
cif_ctrl_val |= ENABLE_CAPTURE;
write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
spin_unlock_irqrestore(&pcdev->lock,flags);
- printk("%s:stream enable CIF_CIF_CTRL 0x%lx",__func__,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
+ printk("%s:stream enable CIF_CIF_CTRL 0x%lx\n",__func__,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
pcdev->fps_timer.istarted = true;
} else {
-/*
- * V4L2 Driver for RK28 camera host
- *
- * Copyright (C) 2006, Sascha Hauer, Pengutronix
- * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK30) ||defined(CONFIG_ARCH_RK3188)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <linux/kthread.h>
-#include <mach/iomux.h>
+
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
#include <media/videobuf-dma-contig.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
-#include <mach/io.h>
-#include <plat/ipp.h>
-#include <plat/vpu_service.h>
+#include <media/videobuf-core.h>
+#include <linux/rockchip/iomap.h>
+
#include "../../video/rockchip/rga/rga.h"
-#if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK3188)
-#include <mach/rk30_camera.h>
-#include <mach/cru.h>
-#include <mach/pmu.h>
-#endif
+#include "../../../arch/arm/mach-rockchip/rk30_camera.h"/*yzm*/
+#include <linux/rockchip/cru.h>
-#if defined(CONFIG_ARCH_RK2928)
+/*******yzm*********
+
+#include <plat/efuse.h>
+#if (defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026))
#include <mach/rk2928_camera.h>
#include <mach/cru.h>
#include <mach/pmu.h>
#define SOFT_RST_CIF1 (SOFT_RST_MAX+1)
#endif
+*/
#include <asm/cacheflush.h>
+
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <media/soc_camera.h>
+#include <media/camsys_head.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
static int debug = 0;
module_param(debug, int, S_IRUGO|S_IWUSR);
-#if defined(CONFIG_TRACE_LOG_PRINTK)
- #define RK30_CAM_DEBUG_TRACE(format, ...) printk(KERN_ERR"rk30_camera: " format, ## __VA_ARGS__)
-#else
- #define RK30_CAM_DEBUG_TRACE(format, ...)
-#endif
-#define RK30_CAM_LOG_TRACE(format, ...) printk(KERN_WARNING"rk30_camera: " format, ## __VA_ARGS__)
+#define CAMMODULE_NAME "rk_cam_cif"
+
+#define wprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_ERR "%s(%d): " fmt,CAMMODULE_NAME,__LINE__,## arg); } while (0)
#define dprintk(level, fmt, arg...) do { \
if (debug >= level) \
- printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0)
+ printk(KERN_ERR"%s(%d): " fmt,CAMMODULE_NAME,__LINE__,## arg); } while (0)
+
+#define RKCAMERA_TR(format, ...) printk(KERN_ERR "%s(%d):" format,CAMMODULE_NAME,__LINE__,## __VA_ARGS__)
+#define RKCAMERA_DG1(format, ...) wprintk(1, format, ## __VA_ARGS__)
+#define RKCAMERA_DG2(format, ...) dprintk(2, format, ## __VA_ARGS__)
+#define debug_printk(format, ...) dprintk(3, format, ## __VA_ARGS__)
-#define RKCAMERA_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
-#define RKCAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
-// CIF Reg Offset
+/* CIF Reg Offset*/
#define CIF_CIF_CTRL 0x00
#define CIF_CIF_INTEN 0x04
#define CIF_CIF_INTSTAT 0x08
#define CIF_CIF_LAST_LINE 0x68
#define CIF_CIF_LAST_PIX 0x6c
-//The key register bit descrition
-// CIF_CTRL Reg , ignore SCM,WBC,ISP,
+/*The key register bit descrition*/
+/* CIF_CTRL Reg , ignore SCM,WBC,ISP,*/
#define DISABLE_CAPTURE (0x00<<0)
#define ENABLE_CAPTURE (0x01<<0)
#define MODE_ONEFRAME (0x00<<1)
#define MODE_LINELOOP (0x02<<1)
#define AXI_BURST_16 (0x0F << 12)
-//CIF_CIF_INTEN
+/*CIF_CIF_INTEN*/
#define FRAME_END_EN (0x01<<1)
#define BUS_ERR_EN (0x01<<6)
#define SCL_ERR_EN (0x01<<7)
-//CIF_CIF_FOR
+/*CIF_CIF_FOR*/
#define VSY_HIGH_ACTIVE (0x01<<0)
#define VSY_LOW_ACTIVE (0x00<<0)
#define HSY_LOW_ACTIVE (0x01<<1)
#define UV_STORAGE_ORDER_UVUV (0x00<<19)
#define UV_STORAGE_ORDER_VUVU (0x01<<19)
-//CIF_CIF_SCL_CTRL
+/*CIF_CIF_SCL_CTRL*/
#define ENABLE_SCL_DOWN (0x01<<0)
#define DISABLE_SCL_DOWN (0x00<<0)
#define ENABLE_SCL_UP (0x01<<1)
#define MIN(x,y) ((x<y) ? x: y)
#define MAX(x,y) ((x>y) ? x: y)
-#define RK_SENSOR_12MHZ 12*1000*1000
#define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */
-#define RK_SENSOR_48MHZ 48*1000*1000
+#define RK_SENSOR_48MHZ 48
+
+#define __raw_readl(p) (*(unsigned long *)(p))
+#define __raw_writel(v,p) (*(unsigned long *)(p) = (v))
#define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base))
#define read_cif_reg(base,addr) __raw_readl(addr+(base))
#define mask_cif_reg(addr, msk, val) write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
+/*
#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)
//CRU,PIXCLOCK
#define CRU_PCLK_REG30 0xbc
#define RQUEST_RST_CIF0 (0x01 << 14)
#define RQUEST_RST_CIF1 (0x01 << 15)
-#define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
-#define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
-#define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
+#define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
+#define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
+#define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
+#endif
+*/
+/*********yzm**********/
+
+static u32 CRU_PCLK_REG30;
+static u32 CRU_CLK_OUT;
+static u32 CRU_CLKSEL29_CON;
+static u32 ENANABLE_INVERT_PCLK_CIF0;
+static u32 DISABLE_INVERT_PCLK_CIF0;
+static u32 ENANABLE_INVERT_PCLK_CIF1;
+static u32 DISABLE_INVERT_PCLK_CIF1;
+static u32 CHIP_NAME;
+
+#define write_cru_reg(addr, val) __raw_writel(val, addr+RK_CRU_VIRT)
+#define read_cru_reg(addr) __raw_readl(addr+RK_CRU_VIRT)
+#define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
+/*********yzm*********end*/
+/*
+#if defined(CONFIG_ARCH_RK2928)
+#define write_cru_reg(addr, val)
+#define read_cru_reg(addr) 0
+#define mask_cru_reg(addr, msk, val)
#endif
+*/
+/*
#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
//GRF_IO_CON3 0x100
#define CIF_DRIVER_STRENGTH_2MA (0x00 << 12)
#define CIF_CLKOUT_AMP_1V8 (0x01 << 10)
#define CIF_CLKOUT_AMP_MASK (0x01 << 26)
-#define write_grf_reg(addr, val) __raw_writel(val, addr+RK30_GRF_BASE)
-#define read_grf_reg(addr) __raw_readl(addr+RK30_GRF_BASE)
-#define mask_grf_reg(addr, msk, val) write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
+#define write_grf_reg(addr, val) __raw_writel(val, addr+RK30_GRF_BASE)
+#define read_grf_reg(addr) __raw_readl(addr+RK30_GRF_BASE)
+#define mask_grf_reg(addr, msk, val) write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
#else
#define write_grf_reg(addr, val)
-#define read_grf_reg(addr) 0
+#define read_grf_reg(addr) 0
#define mask_grf_reg(addr, msk, val)
#endif
+*/
+#define CAM_WORKQUEUE_IS_EN() (false)//(true)
+#define CAM_IPPWORK_IS_EN() (false)/*((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))*/
-#if defined(CONFIG_ARCH_RK2928)
-#define write_cru_reg(addr, val)
-#define read_cru_reg(addr) 0
-#define mask_cru_reg(addr, msk, val)
-#endif
-
-
-//when work_with_ipp is not enabled,CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF is not defined.something wrong with it
-#ifdef CONFIG_VIDEO_RK29_WORK_IPP//CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
-#ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
-#define CAM_WORKQUEUE_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height)\
- || (pcdev->icd_cb.sensor_cb))
-#define CAM_IPPWORK_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))
-#else
-#define CAM_WORKQUEUE_IS_EN() (true)
-#define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
-#endif
-#else //CONFIG_VIDEO_RK29_WORK_IPP
-#define CAM_WORKQUEUE_IS_EN() (false)
-#define CAM_IPPWORK_IS_EN() (false)
-#endif
-
-#define IS_CIF0() (pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)
+#define IS_CIF0() (true)/*(pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)*/
#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
#define CROP_ALIGN_BYTES (0x03)
#define CIF_DO_CROP 0
#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
-#define CROP_ALIGN_BYTES (0x03)
+#define CROP_ALIGN_BYTES (0x0f)
#define CIF_DO_CROP 0
#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
#define CROP_ALIGN_BYTES (0x03)
#define CROP_ALIGN_BYTES (0x0F)
#define CIF_DO_CROP 1
#endif
-//Configure Macro
+
/*
-* Driver Version Note
-*
-*v0.0.x : this driver is 2.6.32 kernel driver;
-*v0.1.x : this driver is 3.0.8 kernel driver;
-*
-*v0.x.1 : this driver first support rk2918;
-*v0.x.2 : fix this driver support v4l2 format is V4L2_PIX_FMT_NV12 and V4L2_PIX_FMT_NV16,is not V4L2_PIX_FMT_YUV420
-* and V4L2_PIX_FMT_YUV422P;
-*v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
-*v0.x.4 : this driver support digital zoom;
-*v0.x.5 : this driver support test framerate and query framerate from board file configuration;
-*v0.x.6 : this driver improve test framerate method;
-*v0.x.7 : digital zoom use the ipp to do scale and crop , otherwise ipp just do the scale. Something wrong with digital zoom if
- we do crop with cif and do scale with ipp , we will fix this next version.
-*v0.x.8 : temp version,reinit capture list when setup video buf.
-*v0.x.9 : 1. add the case of IPP unsupportted ,just cropped by CIF(not do the scale) this version.
- 2. flush workqueue when releas buffer
-*v0.x.a: 1. reset cif and wake up vb when cif have't receive data in a fixed time(now setted as 2 secs) so that app can
- be quitted
- 2. when the flash is on ,flash off in a fixed time to prevent from flash light too hot.
- 3. when front and back camera are the same sensor,and one has the flash ,other is not,flash can't work corrrectly ,fix it
- 4. add menu configs for convineuent to customize sensor series
-*v0.x.b: specify the version is NOT sure stable.
-*v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro
- 2. irq process is splitted to two step.
-*v0.x.e: fix bugs of early suspend when display_pd is closed.
-*v0.x.f: fix calculate ipp memory size is enough or not in try_fmt function;
-*v0.x.11: fix struct rk_camera_work may be reentrant
-*v0.x.13: 1.add scale by arm,rga and pp.
- 2.CIF do the crop when digital zoom.
- 3.fix bug in prob func:request mem twice.
- 4.video_vq may be null when reinit work,fix it
- 5.arm scale algorithm has something wrong(may exceed the bound of width or height) ,fix it.
-*v0.x.15:
-* 1. support rk3066b;
-*v0.4.15:
-* 1. cif work on pingping mode;
-*v0.x.17:
-* 1. support 8Mega picture;
-*v0.x.19:
-* 1. invalidate the limit which scale is invalidat when scale ratio > 2;
-*v0.x.1b: 1. fix oops bug when using arm to do scale_crop if preview buffer is not allocated correctly
- 2. rk_camera_set_fmt will called twice, optimize the procedure. at the first time call ,just to do the sensor init.
-
-*v0.x.1c:
-* 1. fix query resolution error;
-*v0.x.1d:
-* 1. add mv9335+ov5650 driver;
-* 2. fix 2928 digitzoom erro(arm crop scale) of selected zone;
-*v0.x.1f:
-* 1. support rk3188
-*v0.x.21:
- 1. cif change mode to free run.support icatch 7002.
+*v0.1.0 : this driver is 3.10 kernel driver;
+ copy and updata from v0.3.0x19;
+ support rk312x;
+*v0.1.1:
+ 1. spin lock in struct rk_cif_clk is not neccessary,and scheduled func clk_get called in this spin lock scope
+ cause warning, so remove this spin lock .
+*v0.1.2:
+ 1. rk3126 and rk3128 use different dts file.
+*v0.1.3:
+ 1. i2c 1 and wifi use the common io in rk3128,so just enable i2c1 in rk3126 dts file
+*v0.1.4:
+ 1. When cif was at work, the aclk is closed ,may cause bus abnormal ,so sleep 100ms before close aclk
+*v0.1.5:
+ 1. Improve the code to support all configuration.reset,af,flash...
+*v0.1.6:
+ 1. Delete SOCAM_DATAWIDTH_8 in SENSOR_BUS_PARAM parameters,it conflict with V4L2_MBUS_PCLK_SAMPLE_FALLING.
+*v0.1.7:
+ 1. Add power and powerdown controled by PMU.
+*v0.1.8:
+ 1. Support front and rear camera support are the same.
+*v0.1.9:
+ 1. Support pingpong mode.
+ 2. Fix cif_clk_out cannot close which base on XIN24M and cannot turn to 0.
+ 3. Move Camera Sensor Macro from rk_camera.h to rk_camera_sensor_info.h
*/
-#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 4, 0x21)
+#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0x9)
+static int version = RK_CAM_VERSION_CODE;
+module_param(version, int, S_IRUGO);
/* limit to rk29 hardware capabilities */
-#define RK_CAM_BUS_PARAM (SOCAM_MASTER |\
- SOCAM_HSYNC_ACTIVE_HIGH |\
- SOCAM_HSYNC_ACTIVE_LOW |\
- SOCAM_VSYNC_ACTIVE_HIGH |\
- SOCAM_VSYNC_ACTIVE_LOW |\
- SOCAM_PCLK_SAMPLE_RISING |\
- SOCAM_PCLK_SAMPLE_FALLING|\
- SOCAM_DATA_ACTIVE_HIGH |\
- SOCAM_DATA_ACTIVE_LOW|\
+#define RK_CAM_BUS_PARAM (V4L2_MBUS_MASTER |\
+ V4L2_MBUS_HSYNC_ACTIVE_HIGH |\
+ V4L2_MBUS_HSYNC_ACTIVE_LOW |\
+ V4L2_MBUS_VSYNC_ACTIVE_HIGH |\
+ V4L2_MBUS_VSYNC_ACTIVE_LOW |\
+ V4L2_MBUS_PCLK_SAMPLE_RISING |\
+ V4L2_MBUS_PCLK_SAMPLE_FALLING|\
+ V4L2_MBUS_DATA_ACTIVE_HIGH |\
+ V4L2_MBUS_DATA_ACTIVE_LOW|\
SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
#define RK_CAM_W_MIN 48
#define RK_CAM_H_MIN 32
-#define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
+#define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
#define RK_CAM_H_MAX 2764
-#define RK_CAM_FRAME_INVAL_INIT 0
-#define RK_CAM_FRAME_INVAL_DC 0 /* ddl@rock-chips.com : */
-#define RK30_CAM_FRAME_MEASURE 5
+#define RK_CAM_FRAME_INVAL_INIT 0
+#define RK_CAM_FRAME_INVAL_DC 0 /* ddl@rock-chips.com : */
+#define RK30_CAM_FRAME_MEASURE 5
+
+
extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
-
/* buffer for one video frame */
struct rk_camera_buffer
{
enum v4l2_mbus_pixelcode code;
int inwork;
};
-
enum rk_camera_reg_state
{
Reg_Invalidate,
unsigned int cifFmt;
unsigned int cifVirWidth;
unsigned int cifScale;
-// unsigned int VipCrm;
+/* unsigned int VipCrm;*/
enum rk_camera_reg_state Inval;
};
struct rk_camera_work
struct rk_camera_dev *pcdev;
struct work_struct work;
struct list_head queue;
- unsigned int index;
- unsigned int ts;
+ unsigned int index;
};
-
struct rk_camera_frmivalenum
{
struct v4l2_frmivalenum fival;
struct rk_camera_frmivalenum *nxt;
};
-
struct rk_camera_frmivalinfo
{
struct soc_camera_device *icd;
struct rk_camera_frmivalenum *fival_list;
};
-
struct rk_camera_zoominfo
{
struct semaphore sem;
struct v4l2_crop a;
int vir_width;
- int vir_height;
+ int vir_height;
int zoom_rate;
};
-
#if CAMERA_VIDEOBUF_ARM_ACCESS
struct rk29_camera_vbinfo
{
unsigned int size;
};
#endif
-
struct rk_camera_timer{
struct rk_camera_dev *pcdev;
struct hrtimer timer;
bool istarted;
};
-struct rk_cif_clk
+struct rk_cif_clk
{
- //************must modify start************/
- struct clk *pd_cif;
- struct clk *aclk_cif;
+ /************must modify start************/
+ struct clk *pd_cif;
+ struct clk *aclk_cif;
struct clk *hclk_cif;
struct clk *cif_clk_in;
struct clk *cif_clk_out;
- //************must modify end************/
+ /************must modify end************/
- spinlock_t lock;
+ // spinlock_t lock;
bool on;
};
-static struct rk_cif_clk cif_clk[2];
-struct hdr_exposure
-{
- unsigned int set_ts;
- unsigned int get_ts;
- unsigned int code;
-};
-struct rk_hdr_info_s
-{
- bool en;
- struct hdr_exposure frame[3];
-};
+
struct rk_cif_crop
{
spinlock_t lock;
struct v4l2_rect bounds;
};
-#define CONFIG_CIF_STOP_SYNC 1
+struct rk_cif_irqinfo
+{
+ unsigned int irq;
+ unsigned long cifirq_idx;
+ unsigned long cifirq_normal_idx;
+ unsigned long cifirq_abnormal_idx;
+
+ unsigned long dmairq_idx;
+ spinlock_t lock;
+};
struct rk_camera_dev
{
- struct soc_camera_host soc_host;
- struct device *dev;
- /* RK2827x is only supposed to handle one camera on its Quick Capture
- * interface. If anyone ever builds hardware to enable more than
- * one camera, they will have to modify this driver too */
- struct soc_camera_device *icd;
+ struct soc_camera_host soc_host;
+ struct device *dev;
+ /* RK2827x is only supposed to handle one camera on its Quick Capture
+ * interface. If anyone ever builds hardware to enable more than
+ * one camera, they will have to modify this driver too */
+ struct soc_camera_device *icd;
+ void __iomem *base;
+ int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
- //************must modify start************/
- struct clk *pd_cif;
- struct clk *aclk_cif;
- struct clk *hclk_cif;
- struct clk *cif_clk_in;
- struct clk *cif_clk_out;
- //************must modify end************/
- void __iomem *base;
- int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
- unsigned int irq;
- unsigned int fps;
+ unsigned int fps;
unsigned int last_fps;
unsigned long frame_interval;
- unsigned int pixfmt;
- //for ipp
- unsigned int vipmem_phybase;
+ unsigned int pixfmt;
+ /*for ipp */
+ unsigned int vipmem_phybase;
void __iomem *vipmem_virbase;
- unsigned int vipmem_size;
- unsigned int vipmem_bsize;
+ unsigned int vipmem_size;
+ unsigned int vipmem_bsize;
#if CAMERA_VIDEOBUF_ARM_ACCESS
struct rk29_camera_vbinfo *vbinfo;
-#endif
- unsigned int vbinfo_count;
-
- int host_width;
- int host_height;
- int host_left; //sensor output size ?
- int host_top;
- int hostid;
+ unsigned int vbinfo_count;
+#endif
+ int host_width;
+ int host_height;
+ int host_left; /*sensor output size ?*/
+ int host_top;
+ int hostid;
int icd_width;
int icd_height;
+
struct rk_cif_crop cropinfo;
+ struct rk_cif_irqinfo irqinfo;
- struct rk29camera_platform_data *pdata;
- struct resource *res;
- struct list_head capture;
- struct rk_camera_zoominfo zoominfo;
+ struct rk29camera_platform_data *pdata;
+ struct resource *res;
+ struct list_head capture;
+ struct rk_camera_zoominfo zoominfo;
- spinlock_t lock;
+ spinlock_t lock;
struct videobuf_buffer *active0;
struct videobuf_buffer *active1;
- struct rk_camera_reg reginfo_suspend;
- struct workqueue_struct *camera_wq;
- struct rk_camera_work *camera_work;
+ int active_buf;
+ struct rk_camera_reg reginfo_suspend;
+ struct workqueue_struct *camera_wq;
+ struct rk_camera_work *camera_work;
struct list_head camera_work_queue;
spinlock_t camera_work_lock;
- unsigned int camera_work_count;
- struct rk_camera_timer fps_timer;
- struct rk_camera_work camera_reinit_work;
- int icd_init;
- rk29_camera_sensor_cb_s icd_cb;
- struct rk_camera_frmivalinfo icd_frmival[2];
+ unsigned int camera_work_count;
+ struct rk_camera_timer fps_timer;
+ struct rk_camera_work camera_reinit_work;
+ int icd_init;
+ rk29_camera_sensor_cb_s icd_cb;
+ struct rk_camera_frmivalinfo icd_frmival[2];
bool timer_get_fps;
unsigned int reinit_times;
struct videobuf_queue *video_vq;
- volatile bool stop_cif;
-#if CONFIG_CIF_STOP_SYNC
- wait_queue_head_t cif_stop_done;
- volatile bool cif_stopped;
-#endif
+ atomic_t stop_cif;
struct timeval first_tv;
-
- struct rk_hdr_info_s hdr_info;
-// spinlock_t irq_lock;
+
+ int chip_id;
};
static const struct v4l2_queryctrl rk_camera_controls[] =
{
- #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
{
.id = V4L2_CID_ZOOM_ABSOLUTE,
.type = V4L2_CTRL_TYPE_INTEGER,
.maximum = 300,
.step = 5,
.default_value = 100,
- },
- #endif
-
- {
- .id = V4L2_CID_HDR,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "HDR",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0,
}
-
-
};
+static struct rk_cif_clk cif_clk[2];
+
static DEFINE_MUTEX(camera_lock);
static const char *rk_cam_driver_description = "RK_Camera";
static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
static void rk_camera_capture_process(struct work_struct *work);
-// #define OPTIMIZE_MEMORY_USE
+static void rk_camera_diffchips(const char *rockchip_name)
+{
+ if(strstr(rockchip_name,"3128")||strstr(rockchip_name,"3126"))
+ {
+ CRU_PCLK_REG30 = 0xbc;
+ ENANABLE_INVERT_PCLK_CIF0 = ((0x1<<23)|(0x1<<7));
+ DISABLE_INVERT_PCLK_CIF0 = ((0x1<<23)|(0x0<<7));
+ ENANABLE_INVERT_PCLK_CIF1 = ENANABLE_INVERT_PCLK_CIF0;
+ DISABLE_INVERT_PCLK_CIF1 = DISABLE_INVERT_PCLK_CIF0;
+
+ CRU_CLK_OUT = 0xdc;
+ CRU_CLKSEL29_CON = 0xb8;
+
+ CHIP_NAME = 3126;
+ }
+}
+static inline void rk_cru_set_soft_reset(u32 idx, bool on , u32 RK_CRU_SOFTRST_CON)
+{
+ void __iomem *reg = RK_CRU_VIRT + RK_CRU_SOFTRST_CON;
+ u32 val = on ? 0x10001U << 14 : 0x10000U << 14;
+ writel_relaxed(val, reg);
+ dsb();
+}
+
+static void rk_camera_cif_reset(struct rk_camera_dev *pcdev, int only_rst)
+{
+ int ctrl_reg,inten_reg,crop_reg,set_size_reg,for_reg,vir_line_width_reg,scl_reg,y_reg,uv_reg;
+ u32 RK_CRU_SOFTRST_CON = 0;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+ if(strstr(pcdev->pdata->rockchip_name,"3128")||strstr(pcdev->pdata->rockchip_name,"3126"))
+ RK_CRU_SOFTRST_CON = RK312X_CRU_SOFTRSTS_CON(6);
+
+ if (only_rst == true) {
+ rk_cru_set_soft_reset(0, true ,RK_CRU_SOFTRST_CON);
+ udelay(5);
+ rk_cru_set_soft_reset(0, false ,RK_CRU_SOFTRST_CON);
+ } else {
+ ctrl_reg = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+ if (ctrl_reg & ENABLE_CAPTURE) {
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, ctrl_reg&~ENABLE_CAPTURE);
+ }
+ crop_reg = read_cif_reg(pcdev->base,CIF_CIF_CROP);
+ set_size_reg = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
+ inten_reg = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
+ for_reg = read_cif_reg(pcdev->base,CIF_CIF_FOR);
+ vir_line_width_reg = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
+ scl_reg = read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
+ y_reg = read_cif_reg(pcdev->base, CIF_CIF_FRM0_ADDR_Y);
+ uv_reg = read_cif_reg(pcdev->base, CIF_CIF_FRM0_ADDR_UV);
+
+ rk_cru_set_soft_reset(0, true ,RK_CRU_SOFTRST_CON);
+ udelay(5);
+ rk_cru_set_soft_reset(0, false ,RK_CRU_SOFTRST_CON);
+
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, ctrl_reg&~ENABLE_CAPTURE);
+ write_cif_reg(pcdev->base,CIF_CIF_INTEN, inten_reg);
+ write_cif_reg(pcdev->base,CIF_CIF_CROP, crop_reg);
+ write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, set_size_reg);
+ write_cif_reg(pcdev->base,CIF_CIF_FOR, for_reg);
+ write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,vir_line_width_reg);
+ write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,scl_reg);
+ write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y,y_reg); /*ddl@rock-chips.com v0.3.0x13 */
+ write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV,uv_reg);
+ }
+ return;
+}
+
/*
* Videobuf operations
unsigned int *size)
{
struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
unsigned int i;
struct rk_camera_work *wk;
int bytes_per_line_host;
fmt.packing = SOC_MBUS_PACKING_1_5X8;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
icd->current_fmt->host_fmt);
if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB565)
else
bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
icd->current_fmt->host_fmt);
+ /* dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);*/ /*yzm*/
if (bytes_per_line_host < 0)
return bytes_per_line_host;
pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
if (CAM_WORKQUEUE_IS_EN()) {
- #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
- if (CAM_IPPWORK_IS_EN())
- #endif
- {
+
+ if (CAM_IPPWORK_IS_EN()) {
BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
- #ifndef OPTIMIZE_MEMORY_USE
if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
*count = pcdev->vipmem_size/pcdev->vipmem_bsize;
}
- #endif
}
+
if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
kfree(pcdev->camera_work);
pcdev->camera_work = NULL;
if (pcdev->camera_work == NULL) {
pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
if (pcdev->camera_work == NULL) {
- RK30_CAM_DEBUG_TRACE("\n %s kmalloc fail\n", __FUNCTION__);
+ RKCAMERA_TR("kmalloc failed\n");
BUG();
}
INIT_LIST_HEAD(&pcdev->camera_work_queue);
if (pcdev->vbinfo == NULL) {
pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL);
if (pcdev->vbinfo == NULL) {
- RK30_CAM_DEBUG_TRACE("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
+ RKCAMERA_TR("vbinfo kmalloc fail\n");
BUG();
}
memset(pcdev->vbinfo,0,sizeof(struct rk29_camera_vbinfo)*(*count));
}
#endif
}
-
- pcdev->vbinfo_count = *count;
pcdev->video_vq = vq;
- RK30_CAM_DEBUG_TRACE("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
+ RKCAMERA_DG1("videobuf size:%d, vipmem_buf size:%d, count:%d \n",*size,pcdev->vipmem_size, *count);
return 0;
}
{
struct soc_camera_device *icd = vq->priv_data;
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+
+ dev_dbg(icd->control, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,/*yzm*/
&buf->vb, buf->vb.baddr, buf->vb.bsize);
/* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
* This waits until this buffer is out of danger, i.e., until it is no
* longer in STATE_QUEUED or STATE_ACTIVE
*/
- //videobuf_waiton(vq, &buf->vb, 0, 0);
+ videobuf_waiton(vq, &buf->vb, 0, 0);
videobuf_dma_contig_free(vq, &buf->vb);
- dev_dbg(&icd->dev, "%s freed\n", __func__);
+ /*dev_dbg(&icd->dev, "%s freed\n", __func__);*/ /*yzm*/
buf->vb.state = VIDEOBUF_NEEDS_INIT;
return;
}
int ret;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
icd->current_fmt->host_fmt);
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
if ((bytes_per_line < 0) || (vb->boff == 0))
return -EINVAL;
buf = container_of(vb, struct rk_camera_buffer, vb);
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
- vb, vb->baddr, vb->bsize);
+ /*dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,*/ /*yzm*/
+ /* vb, vb->baddr, vb->bsize);*/ /*yzm*/
/* Added list head initialization on alloc */
WARN_ON(!list_empty(&vb->queue));
BUG_ON(NULL == icd->current_fmt);
if (buf->code != icd->current_fmt->code ||
- vb->width != icd->user_width ||
- vb->height != icd->user_height ||
- vb->field != field) {
+ vb->width != icd->user_width ||
+ vb->height != icd->user_height ||
+ vb->field != field) {
buf->code = icd->current_fmt->code;
vb->width = icd->user_width;
vb->height = icd->user_height;
return ret;
}
-#if 0
-static void rk_camera_store_register(struct rk_camera_dev *pcdev)
-{
-#if defined(CONFIG_ARCH_RK3188)
- pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
- pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
- pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
- pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
- pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
- pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
- pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
-
- cru_set_soft_reset(SOFT_RST_CIF0, true);
- udelay(3);
- cru_set_soft_reset(SOFT_RST_CIF0, false);
-
-#endif
-}
-static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
-{
-#if defined(CONFIG_ARCH_RK3188)
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
- write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
- write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
- write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
- write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
- write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
- write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
-#endif
-}
-#endif
-
static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev, int fmt_ready)
{
unsigned int y_addr,uv_addr;
struct rk_camera_dev *pcdev = rk_pcdev;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+
if (vb) {
- if (CAM_WORKQUEUE_IS_EN()) {
- #ifdef OPTIMIZE_MEMORY_USE
- y_addr = vb->boff;
- uv_addr = y_addr + vb->width * vb->height;
- #else
+ if (CAM_WORKQUEUE_IS_EN() & CAM_IPPWORK_IS_EN()) {
y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
uv_addr = y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
- RK30_CAM_DEBUG_TRACE("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
+ RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
BUG();
}
- #endif
} else {
y_addr = vb->boff;
uv_addr = y_addr + vb->width * vb->height;
}
-
- switch(fmt_ready)
- {
- case 0:
- write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
- write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
- break;
- case 1:
- write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
- write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
- break;
- default:
- RK30_CAM_DEBUG_TRACE("%s(%d): fmt_ready(%d) is wrong!\n", __FUNCTION__, __LINE__,fmt_ready);
- break;
- }
-
+#if defined(CONFIG_ARCH_RK3188)
+ rk_camera_cif_reset(pcdev,false);
+#endif
+
+ switch(fmt_ready)
+ {
+ case 0:
+ write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
+ write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
+ break;
+ case 1:
+ write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
+ write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
+ break;
+ default:
+ printk("%s(%d): fmt_ready(%d) is wrong!\n", __FUNCTION__, __LINE__,fmt_ready);
+ break;
+ }
+
}
}
/* Locking: Caller holds q->irqlock */
struct videobuf_buffer *vb)
{
struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
#if CAMERA_VIDEOBUF_ARM_ACCESS
struct rk29_camera_vbinfo *vb_info;
#endif
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
- vb, vb->baddr, vb->bsize);
- // spin_lock_irqsave(&pcdev->irq_lock, flags);
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
vb->state = VIDEOBUF_QUEUED;
if (list_empty(&pcdev->capture)) {
vb_info->size = vb->bsize;
vb_info->phy_addr = vb->boff;
} else {
- RK30_CAM_DEBUG_TRACE("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
+ RKCAMERA_TR("ioremap videobuf %d failed\n",vb->i);
}
}
}
-#endif
- if((((read_cif_reg(pcdev->base,CIF_CIF_CTRL)) & ENABLE_CAPTURE) == 0)){
- if (!pcdev->active0) {
- pcdev->active0 = vb;
- rk_videobuf_capture(vb,pcdev,0);
- list_del_init(&(vb->queue));
- } else if (!pcdev->active1) {
- pcdev->active1 = vb;
- rk_videobuf_capture(vb,pcdev,1);
- list_del_init(&(vb->queue));
- }
- }
- //spin_unlock_irqrestore(&pcdev->irq_lock, flags);
-}
-static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
-{
- switch (pixfmt)
- {
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- {
- *ippfmt = IPP_Y_CBCR_H2V1;
- break;
- }
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- {
- *ippfmt = IPP_Y_CBCR_H2V2;
- break;
- }
- default:
- goto rk_pixfmt2ippfmt_err;
- }
+#endif
- return 0;
-rk_pixfmt2ippfmt_err:
- return -1;
+ if (!pcdev->active0) {
+ pcdev->active0 = vb;
+ rk_videobuf_capture(vb,pcdev,0);
+ /*if (atomic_read(&pcdev->stop_cif) == false) { //ddl@rock-chips.com v0.3.0x13
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
+ } */
+ list_del_init(&(vb->queue));
+ } else if (!pcdev->active1) {
+ pcdev->active1 = vb;
+ rk_videobuf_capture(vb,pcdev,1);
+ /*if (atomic_read(&pcdev->stop_cif) == false) { //ddl@rock-chips.com v0.3.0x13
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
+ } */
+ list_del_init(&(vb->queue));
+ }
+
}
-#if 0
+#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
{
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
switch (pixfmt)
{
case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_UYVY: // yuv 422, but sensor has defined this format(in fact ,should be defined yuv 420), treat this as yuv 420.
+ case V4L2_PIX_FMT_UYVY: /* yuv 422, but sensor has defined this format(in fact ,should be defined yuv 420), treat this as yuv 420.*/
case V4L2_PIX_FMT_YUYV:
{
*ippfmt = RK_FORMAT_YCbCr_420_SP;
return -1;
}
#endif
-
#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
static int rk_camera_scale_crop_pp(struct work_struct *work){
struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
unsigned long int flags;
int scale_times,w,h;
int src_y_offset;
- PP_OP_HANDLE hnd;
- PP_OPERATION init;
int ret = 0;
- vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
-
- memset(&init, 0, sizeof(init));
- init.srcAddr = vipdata_base;
- init.srcFormat = PP_IN_FORMAT_YUV420SEMI;
- init.srcWidth = init.srcHStride = pcdev->zoominfo.vir_width;
- init.srcHeight = init.srcVStride = pcdev->zoominfo.vir_height;
-
- init.dstAddr = vb->boff;
- init.dstFormat = PP_OUT_FORMAT_YUV420INTERLAVE;
- init.dstWidth = init.dstHStride = pcdev->icd->user_width;
- init.dstHeight = init.dstVStride = pcdev->icd->user_height;
-
- printk("srcWidth = %d,srcHeight = %d,dstWidth = %d,dstHeight = %d\n",init.srcWidth,init.srcHeight,init.dstWidth,init.dstHeight);
- #if 0
- ret = ppOpInit(&hnd, &init);
- if (!ret) {
- ppOpPerform(hnd);
- ppOpSync(hnd);
- ppOpRelease(hnd);
- } else {
- printk("can not create ppOp handle\n");
- }
- #endif
+
return ret;
}
#endif
int rga_times = 3;
const struct soc_mbus_pixelfmt *fmt;
int ret = 0;
- fmt = soc_mbus_get_fmtdesc(pcdev->icd->current_fmt->code);
- vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
- if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565)
- && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){
- RK30_CAM_DEBUG_TRACE("RGA not support this format !\n");
- goto do_ipp_err;
- }
- if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) {
- scale_times = MAX((pcdev->icd->user_width/0x800),(pcdev->icd->user_height/0x800));
- scale_times++;
- } else {
- scale_times = 1;
- }
- session.pid = current->pid;
- INIT_LIST_HEAD(&session.waiting);
- INIT_LIST_HEAD(&session.running);
- INIT_LIST_HEAD(&session.list_session);
- init_waitqueue_head(&session.wait);
- /* no need to protect */
- list_add_tail(&session.list_session, &rga_service.session);
- atomic_set(&session.task_running, 0);
- atomic_set(&session.num_done, 0);
-
- memset(&req,0,sizeof(struct rga_req));
- req.src.act_w = pcdev->zoominfo.a.c.width/scale_times;
- req.src.act_h = pcdev->zoominfo.a.c.height/scale_times;
-
- req.src.vir_w = pcdev->zoominfo.vir_width;
- req.src.vir_h =pcdev->zoominfo.vir_height;
- req.src.yrgb_addr = vipdata_base;
- req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
- req.src.v_addr = req.src.uv_addr ;
- req.src.format =fmt->fourcc;
- rk_pixfmt2rgafmt(fmt->fourcc,&req.src.format);
- req.src.x_offset = pcdev->zoominfo.a.c.left;
- req.src.y_offset = pcdev->zoominfo.a.c.top;
-
- req.dst.act_w = pcdev->icd->user_width/scale_times;
- req.dst.act_h = pcdev->icd->user_height/scale_times;
-
- req.dst.vir_w = pcdev->icd->user_width;
- req.dst.vir_h = pcdev->icd->user_height;
- req.dst.x_offset = 0;
- req.dst.y_offset = 0;
- req.dst.yrgb_addr = vb->boff;
- rk_pixfmt2rgafmt(pcdev->icd->current_fmt->host_fmt->fourcc,&req.dst.format);
- req.clip.xmin = 0;
- req.clip.xmax = req.dst.vir_w-1;
- req.clip.ymin = 0;
- req.clip.ymax = req.dst.vir_h -1;
-
- req.rotate_mode = 1;
- req.scale_mode = 2;
-
- req.sina = 0;
- req.cosa = 65536;
- req.mmu_info.mmu_en = 0;
-
- for (h=0; h<scale_times; h++) {
- for (w=0; w<scale_times; w++) {
- rga_times = 3;
-
- req.src.yrgb_addr = vipdata_base;
- req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
- req.src.x_offset = pcdev->zoominfo.a.c.left+w*pcdev->zoominfo.a.c.width/scale_times;
- req.src.y_offset = pcdev->zoominfo.a.c.top+h*pcdev->zoominfo.a.c.height/scale_times;
- req.dst.x_offset = pcdev->icd->user_width*w/scale_times;
- req.dst.y_offset = pcdev->icd->user_height*h/scale_times;
- req.dst.yrgb_addr = vb->boff ;
- // RK30_CAM_DEBUG_TRACE("src.act_w = %d , src.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset);
- // RK30_CAM_DEBUG_TRACE("dst.act_w = %d , dst.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset);
- // RK30_CAM_DEBUG_TRACE("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
-
- while(rga_times-- > 0) {
- if (rga_blit_sync(&session, &req)){
- RK30_CAM_DEBUG_TRACE("rga do erro,do again,rga_times = %d!\n",rga_times);
- } else {
- break;
- }
- }
-
- if (rga_times <= 0) {
- spin_lock_irqsave(&pcdev->lock, flags);
- vb->state = VIDEOBUF_NEEDS_INIT;
- spin_unlock_irqrestore(&pcdev->lock, flags);
- mutex_lock(&rga_service.lock);
- list_del(&session.list_session);
- rga_service_session_clear(&session);
- mutex_unlock(&rga_service.lock);
- goto session_done;
- }
- }
- }
- session_done:
- mutex_lock(&rga_service.lock);
- list_del(&session.list_session);
- rga_service_session_clear(&session);
- mutex_unlock(&rga_service.lock);
- do_ipp_err:
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
return ret;
}
#endif
-#if ((defined(CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON)) && (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP))
+#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
static int rk_camera_scale_crop_ipp(struct work_struct *work)
{
- struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
- struct videobuf_buffer *vb = camera_work->vb;
- struct rk_camera_dev *pcdev = camera_work->pcdev;
- int vipdata_base;
- unsigned long int flags;
-
- struct rk29_ipp_req ipp_req;
- int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
- int scale_times,w,h;
- int ret = 0;
- /*
- *ddl@rock-chips.com:
- * IPP Dest image resolution is 2047x1088, so scale operation break up some times
- */
- if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
- scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
- scale_times++;
- } else {
- scale_times = 1;
- }
- memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
-#ifdef OPTIMIZE_MEMORY_USE
- //need copy to ipp buffer?
- if((pcdev->zoominfo.a.c.width != pcdev->zoominfo.vir_width)
- ||(pcdev->zoominfo.a.c.height != pcdev->zoominfo.vir_height)){
- if((pcdev->zoominfo.vir_width != pcdev->icd->user_width) || (pcdev->zoominfo.vir_height != pcdev->icd->user_height)){
- printk("OPTIMIZE_MEMORY_USE erro: src size not equal to dst size\n");
- goto do_ipp_err;
- }
- ipp_req.timeout = 3000;
- ipp_req.flag = IPP_ROT_0;
- ipp_req.store_clip_mode =1;
- ipp_req.src0.w = pcdev->zoominfo.vir_width/scale_times;
- ipp_req.src0.h = pcdev->zoominfo.vir_height/scale_times;
- ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
- ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
- ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
- ipp_req.dst_vir_w = pcdev->icd->user_width;
- rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
- rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
- vipdata_base = pcdev->vipmem_phybase;
- src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem
- dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
- for (h=0; h<scale_times; h++) {
- for (w=0; w<scale_times; w++) {
- src_y_offset = (h*pcdev->zoominfo.vir_height/scale_times)* pcdev->zoominfo.vir_width
- + w*pcdev->zoominfo.vir_width/scale_times;
- src_uv_offset = (h*pcdev->zoominfo.vir_height/scale_times)* pcdev->zoominfo.vir_width/2
- + w*pcdev->zoominfo.vir_width/scale_times;
-
- dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
- dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
- ipp_req.src0.YrgbMst = vb->boff + src_y_offset;
- ipp_req.src0.CbrMst = vb->boff + src_y_size + src_uv_offset;
- ipp_req.dst0.YrgbMst = vipdata_base + dst_y_offset;
- ipp_req.dst0.CbrMst = vipdata_base + dst_y_size + dst_uv_offset;
- if (ipp_blit_sync(&ipp_req)){
- RK30_CAM_DEBUG_TRACE("ipp do erro\n");
- }
- }
- }
- memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
- }
-#endif
-
- ipp_req.timeout = 3000;
- ipp_req.flag = IPP_ROT_0;
- ipp_req.store_clip_mode =1;
- ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
- ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
- ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
- rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
- ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
- ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
- ipp_req.dst_vir_w = pcdev->icd->user_width;
- rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
-#ifdef OPTIMIZE_MEMORY_USE
- if((pcdev->zoominfo.a.c.width != pcdev->zoominfo.vir_width)
- ||(pcdev->zoominfo.a.c.height != pcdev->zoominfo.vir_height)){
- vipdata_base = pcdev->vipmem_phybase;
- }else
- vipdata_base = vb->boff;
-
-#else
- vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
-#endif
- src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem
- dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
- for (h=0; h<scale_times; h++) {
- for (w=0; w<scale_times; w++) {
- int ipp_times = 3;
- src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width
- + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
- src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width/2
- + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
-
- dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
- dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
-
- ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
- ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
- ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
- ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
- while(ipp_times-- > 0) {
- if (ipp_blit_sync(&ipp_req)){
- RK30_CAM_DEBUG_TRACE("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
- } else {
- break;
- }
- }
-
- if (ipp_times <= 0) {
- spin_lock_irqsave(&pcdev->lock, flags);
- vb->state = VIDEOBUF_NEEDS_INIT;
- spin_unlock_irqrestore(&pcdev->lock, flags);
- RK30_CAM_DEBUG_TRACE("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
- RK30_CAM_DEBUG_TRACE("widx:%d hidx:%d ",w,h);
- RK30_CAM_DEBUG_TRACE("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height);
- RK30_CAM_DEBUG_TRACE("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
- RK30_CAM_DEBUG_TRACE("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
- RK30_CAM_DEBUG_TRACE("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
- RK30_CAM_DEBUG_TRACE("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
- RK30_CAM_DEBUG_TRACE("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
- RK30_CAM_DEBUG_TRACE("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
- RK30_CAM_DEBUG_TRACE("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w);
- RK30_CAM_DEBUG_TRACE("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
-
- goto do_ipp_err;
- }
- }
- }
-
-do_ipp_err:
- return ret;
-}
-#endif
-#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
-static int rk_camera_scale_crop_arm(struct work_struct *work)
-{
- struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
- struct videobuf_buffer *vb = camera_work->vb;
- struct rk_camera_dev *pcdev = camera_work->pcdev;
- struct rk29_camera_vbinfo *vb_info;
- unsigned char *psY,*pdY,*psUV,*pdUV;
- unsigned char *src,*dst;
- unsigned long src_phy,dst_phy;
- int srcW,srcH,cropW,cropH,dstW,dstH;
- long zoomindstxIntInv,zoomindstyIntInv;
- long x,y;
- long yCoeff00,yCoeff01,xCoeff00,xCoeff01;
- long sX,sY;
- long r0,r1,a,b,c,d;
- int ret = 0;
-
- src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
- src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize);
- psUV = psY + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
-
- srcW = pcdev->zoominfo.vir_width;
- srcH = pcdev->zoominfo.vir_height;
- cropW = pcdev->zoominfo.a.c.width;
- cropH = pcdev->zoominfo.a.c.height;
-
- psY = psY + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width+pcdev->zoominfo.a.c.left;
- psUV = psUV + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width/2+pcdev->zoominfo.a.c.left;
-
- vb_info = pcdev->vbinfo+vb->i;
- dst_phy = vb_info->phy_addr;
- dst = pdY = (unsigned char*)vb_info->vir_addr;
- pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height;
- dstW = pcdev->icd->user_width;
- dstH = pcdev->icd->user_height;
-
- zoomindstxIntInv = ((unsigned long)(cropW)<<16)/dstW + 1;
- zoomindstyIntInv = ((unsigned long)(cropH)<<16)/dstH + 1;
- //y
- //for(y = 0; y<dstH - 1 ; y++ ) {
- for(y = 0; y<dstH; y++ ) {
- yCoeff00 = (y*zoomindstyIntInv)&0xffff;
- yCoeff01 = 0xffff - yCoeff00;
- sY = (y*zoomindstyIntInv >> 16);
- sY = (sY >= srcH - 1)? (srcH - 2) : sY;
- for(x = 0; x<dstW; x++ ) {
- xCoeff00 = (x*zoomindstxIntInv)&0xffff;
- xCoeff01 = 0xffff - xCoeff00;
- sX = (x*zoomindstxIntInv >> 16);
- sX = (sX >= srcW -1)?(srcW- 2) : sX;
- a = psY[sY*srcW + sX];
- b = psY[sY*srcW + sX + 1];
- c = psY[(sY+1)*srcW + sX];
- d = psY[(sY+1)*srcW + sX + 1];
-
- r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
- r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
- r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
-
- pdY[x] = r0;
- }
- pdY += dstW;
- }
-
- dstW /= 2;
- dstH /= 2;
- srcW /= 2;
- srcH /= 2;
-
- //UV
- //for(y = 0; y<dstH - 1 ; y++ ) {
- for(y = 0; y<dstH; y++ ) {
- yCoeff00 = (y*zoomindstyIntInv)&0xffff;
- yCoeff01 = 0xffff - yCoeff00;
- sY = (y*zoomindstyIntInv >> 16);
- sY = (sY >= srcH -1)? (srcH - 2) : sY;
- for(x = 0; x<dstW; x++ ) {
- xCoeff00 = (x*zoomindstxIntInv)&0xffff;
- xCoeff01 = 0xffff - xCoeff00;
- sX = (x*zoomindstxIntInv >> 16);
- sX = (sX >= srcW -1)?(srcW- 2) : sX;
- //U
- a = psUV[(sY*srcW + sX)*2];
- b = psUV[(sY*srcW + sX + 1)*2];
- c = psUV[((sY+1)*srcW + sX)*2];
- d = psUV[((sY+1)*srcW + sX + 1)*2];
-
- r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
- r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
- r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
-
- pdUV[x*2] = r0;
-
- //V
- a = psUV[(sY*srcW + sX)*2 + 1];
- b = psUV[(sY*srcW + sX + 1)*2 + 1];
- c = psUV[((sY+1)*srcW + sX)*2 + 1];
- d = psUV[((sY+1)*srcW + sX + 1)*2 + 1];
-
- r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
- r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
- r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
-
- pdUV[x*2 + 1] = r0;
- }
- pdUV += dstW*2;
- }
-
-rk_camera_scale_crop_arm_end:
-
- dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize));
- outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize));
-
- dmac_flush_range((void*)dst,(void*)(dst+vb_info->size));
- outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size));
-
- return ret;
+
+ return 0;
}
#endif
-
static void rk_camera_capture_process(struct work_struct *work)
{
struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
struct videobuf_buffer *vb = camera_work->vb;
struct rk_camera_dev *pcdev = camera_work->pcdev;
- //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code;
- struct device *control = to_soc_camera_control(pcdev->icd);
- struct v4l2_subdev *sd=dev_get_drvdata(control);
+ /*enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code; */
unsigned long flags = 0;
- int err = 0,i;
+ int err = 0;
- if (!CAM_WORKQUEUE_IS_EN())
- goto rk_camera_capture_process_end;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
- camera_work->vb->rk_code = 0x00;
- if (pcdev->hdr_info.en) {
- printk("rk_camera_capture_process hdr %d fps\n",camera_work->ts);
- if (pcdev->hdr_info.frame[0].set_ts == 0) {
- v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,(void*)pcdev->hdr_info.frame[0].code);
- pcdev->hdr_info.frame[0].set_ts = pcdev->fps;
- printk("set hdr %d @ %d fps\n",0,pcdev->fps);
- } else {
- if ((camera_work->ts - pcdev->hdr_info.frame[0].set_ts) > 1) {
- for (i=0; i<3; i++) {
- if (pcdev->hdr_info.frame[i].get_ts == 0) {
- printk("get hdr %d @ %d fps %dx%d\n",i,camera_work->ts,camera_work->vb->width,camera_work->vb->height);
- pcdev->hdr_info.frame[i].get_ts = camera_work->ts;
- RK_VIDEOBUF_CODE_SET(camera_work->vb->rk_code,pcdev->hdr_info.frame[i].code);
- break;
- }
- }
- if (i==2) {
- v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,(void*)RK_VIDEOBUF_HDR_EXPOSURE_FINISH);
- pcdev->hdr_info.en = false;
- printk("hdr off\n");
- }
- }
- }
+ if (atomic_read(&pcdev->stop_cif)==true) {
+ err = -EINVAL;
+ goto rk_camera_capture_process_end;
}
+ if (!CAM_WORKQUEUE_IS_EN()) {
+ err = -EINVAL;
+ goto rk_camera_capture_process_end;
+ }
down(&pcdev->zoominfo.sem);
if (pcdev->icd_cb.scale_crop_cb){
}
}
spin_lock_irqsave(&pcdev->camera_work_lock, flags);
- list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
+ list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);
- wake_up(&(camera_work->vb->done));
+ wake_up(&(camera_work->vb->done)); /* ddl@rock-chips.com : v0.3.9 */
return;
}
-#if defined(CONFIG_ARCH_RK3188)
-static void rk_camera_store_resore_register(struct rk_camera_dev *pcdev)
+
+static void rk_camera_cifrest_delay(struct work_struct *work)
{
+ struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
+ struct rk_camera_dev *pcdev = camera_work->pcdev;
+ unsigned long flags = 0;
- pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
- pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
- pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
- pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
- pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
- pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
- pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
-
- cru_set_soft_reset(SOFT_RST_CIF0, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF0, false);
-
- if (pcdev->reginfo_suspend.cifCtrl&ENABLE_CAPTURE)
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
- write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
- write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
- write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
- write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
- write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
- write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
+ mdelay(1);
+ rk_camera_cif_reset(pcdev,false);
+
+ spin_lock_irqsave(&pcdev->camera_work_lock, flags);
+ list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
+ spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);
+
+ spin_lock_irqsave(&pcdev->lock,flags);
+ if (atomic_read(&pcdev->stop_cif) == false) {
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
+ RKCAMERA_DG2("After reset cif, enable capture again!\n");
+ }
+ spin_unlock_irqrestore(&pcdev->lock,flags);
+ return;
+}
+
+static inline irqreturn_t rk_camera_cifirq(int irq, void *data)
+{
+ struct rk_camera_dev *pcdev = data;
+ struct rk_camera_work *wk;
+ unsigned int reg_cifctrl, reg_lastpix, reg_lastline;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+
+ write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
+
+ reg_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+ reg_lastpix = read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX);
+ reg_lastline = read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE);
+ pcdev->irqinfo.cifirq_idx++;
+ if ((reg_lastline != pcdev->host_height) /*|| (reg_lastpix != pcdev->host_width)*/) {
+ pcdev->irqinfo.cifirq_abnormal_idx = pcdev->irqinfo.cifirq_idx;
+ RKCAMERA_DG2("Cif irq-%ld is error, %dx%d != %dx%d\n",pcdev->irqinfo.cifirq_abnormal_idx,
+ reg_lastpix,reg_lastline,pcdev->host_width,pcdev->host_height);
+ } else {
+ pcdev->irqinfo.cifirq_normal_idx = pcdev->irqinfo.cifirq_idx;
+ }
+/*
+ if(reg_cifctrl & ENABLE_CAPTURE) {
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (reg_cifctrl & ~ENABLE_CAPTURE));
+ }
+*/
+ if (pcdev->irqinfo.cifirq_abnormal_idx>0) {
+ if ((pcdev->irqinfo.cifirq_idx - pcdev->irqinfo.cifirq_abnormal_idx) == 1 ) {
+ if (!list_empty(&pcdev->camera_work_queue)) {
+ RKCAMERA_DG2("Receive cif irq-%ld and queue work to cif reset\n",pcdev->irqinfo.cifirq_idx);
+ wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
+ list_del_init(&wk->queue);
+ INIT_WORK(&(wk->work), rk_camera_cifrest_delay);
+ wk->pcdev = pcdev;
+ queue_work(pcdev->camera_wq, &(wk->work));
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
}
-#endif
-static irqreturn_t rk_camera_irq(int irq, void *data)
+static inline irqreturn_t rk_camera_dmairq(int irq, void *data)
{
struct rk_camera_dev *pcdev = data;
struct videobuf_buffer *vb;
struct rk_camera_work *wk;
struct timeval tv;
- unsigned long tmp_intstat;
- unsigned long tmp_cifctrl;
- unsigned long tmp_cif_frmst;
+ unsigned long reg_cifctrl;
+ unsigned long tmp_cif_frmst;
struct videobuf_buffer **active = 0;
+ struct videobuf_buffer *active_buf = NULL;
int flag = 0;
- unsigned int invalid_y_addr ,invalid_uv_addr;
-#ifdef OPTIMIZE_MEMORY_USE
- invalid_y_addr = 0/*pcdev->vipmem_phybase + pcdev->vipmem_bsize*/;
- invalid_uv_addr = 0/*invalid_y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height*/;
-#else
- invalid_y_addr = pcdev->vipmem_phybase + pcdev->vbinfo_count *pcdev->vipmem_bsize;
- invalid_uv_addr = invalid_y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
-#endif
- tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
- tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
- tmp_cif_frmst = read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS);
-#if (CONFIG_CIF_STOP_SYNC == 0)
- if(pcdev->stop_cif == true) {
- //RK30_CAM_DEBUG_TRACE("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__);
- write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
- return IRQ_HANDLED;
- }
-#endif
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
- if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/) {//bit9 =1 ,bit0 = 0
- write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
- // if(tmp_cifctrl & ENABLE_CAPTURE)
- // write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
- return IRQ_HANDLED;
- }
-
- /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
- if (tmp_cif_frmst & (CIF_F0_READY | CIF_F1_READY)) {
- write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
-#if CONFIG_CIF_STOP_SYNC
- if(pcdev->stop_cif == true) {
- //RK30_CAM_DEBUG_TRACE("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__);
- write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
-
-#if 1
- // write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0); //capture complete interrupt enable
- {
-#if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928))
- mdelay(100);
- if(IS_CIF0()){
- cru_set_soft_reset(SOFT_RST_CIF0, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF0, false);
-
- }else{
- cru_set_soft_reset(SOFT_RST_CIF1, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF1, false);
- }
-#elif defined(CONFIG_ARCH_RK3188)
- cru_set_soft_reset(SOFT_RST_CIF0, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF0, false);
-#endif
- }
-#endif
- spin_lock(&pcdev->lock);
- pcdev->cif_stopped = true;
- wake_up(&pcdev->cif_stop_done);
- spin_unlock(&pcdev->lock);
- return IRQ_HANDLED;
- }
-#endif
- if (!pcdev->fps) {
+
+ reg_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+ tmp_cif_frmst = read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS);
+ /* ddl@rock-chps.com : Current VIP is run in Pingpong Frame Mode */
+ if (tmp_cif_frmst & (CIF_F0_READY | CIF_F1_READY)) { //frame 0 or 1 ready yzm
+ write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
+
+ pcdev->irqinfo.dmairq_idx++;
+ if (pcdev->irqinfo.cifirq_abnormal_idx == pcdev->irqinfo.dmairq_idx) {
+ write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
+ goto end;
+ }
+
+ if (!pcdev->fps) {//µÚÒ»´Î½øÈëÖжÏ
do_gettimeofday(&pcdev->first_tv);
}
-process_another_frame:
+
if((tmp_cif_frmst & CIF_F0_READY) && (tmp_cif_frmst & CIF_F1_READY)){
- printk(KERN_DEBUG"%s:f0 && f1 ready ,need to resart cif!!!!!\n",__func__);
- spin_lock(&pcdev->lock);
-
- rk_camera_store_resore_register(pcdev);
- rk_videobuf_capture(pcdev->active0,pcdev,0);
- rk_videobuf_capture(pcdev->active1,pcdev,1);
- tmp_cifctrl &=~ENABLE_CAPTURE;
- spin_unlock(&pcdev->lock);
+ printk("%s:f0 && f1 ready ,need to resart cif!!!!!\n",__func__);
+ reg_cifctrl &=~ENABLE_CAPTURE;
- goto RK_CAMERA_IRQ_END;
+ goto end;
}
- pcdev->fps++;
-
+ pcdev->fps++;
+
if (tmp_cif_frmst & CIF_F0_READY){
active = &pcdev->active0;
flag = 0;
flag = 1;
} else {
printk("irq frame status erro \n");
- goto RK_CAMERA_IRQ_END;
+ goto end;
}
-#if 0
if (!(*active)){
- goto RK_CAMERA_IRQ_END;
+ printk("active = NULL\n");
+ goto end;
}
-#endif
- if (pcdev->frame_inval>0) {
- pcdev->frame_inval--;
+
+ if (pcdev->frame_inval>0) {//¹ØÓÚ¹ýÂËÇ°¼¸Ö¡µÄ£¬ÏÖÔÚûÓÐÓõ½
+ pcdev->frame_inval--;
rk_videobuf_capture(*active,pcdev,flag);
- goto first_frame_done;
- } else if (pcdev->frame_inval) {
- RK30_CAM_DEBUG_TRACE("frame_inval : %0x",pcdev->frame_inval);
- pcdev->frame_inval = 0;
- }
+ } else if (pcdev->frame_inval) {
+ RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
+ pcdev->frame_inval = 0;
+ }
- if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
- do_gettimeofday(&tv);
- pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
- /(RK30_CAM_FRAME_MEASURE-1);
+ if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {//¹ýÂËÇ°¼¸Ö¡,¿ªÊ¼¶¨Ê±
+ do_gettimeofday(&tv);
+ pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
+ /(RK30_CAM_FRAME_MEASURE-1);
+ }
+
+ vb = *active;
+
+ if (!vb) {
+ printk("no acticve buffer!!!\n");
+ goto end;
}
-
- vb = *active;
-
-#if 0
- if(!vb){
- RK30_CAM_DEBUG_TRACE("no acticve buffer!!!\n");
- goto RK_CAMERA_IRQ_END;
- }
- if (vb->stream.prev != &(pcdev->video_vq->stream)) {
- RK30_CAM_DEBUG_TRACE("vb(%d) isn't first node in stream list\n", vb->i);
- goto RK_CAMERA_IRQ_END;
- }
-#endif
- *active = NULL;
- spin_lock(&pcdev->lock);
- if (!list_empty(&pcdev->capture)) {
- *active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
- if (*active) {
- WARN_ON((*active)->state != VIDEOBUF_QUEUED);
- if (tmp_cif_frmst & CIF_F0_READY){
- pcdev->active0 = *active;
- } else if (tmp_cif_frmst & CIF_F1_READY){
- pcdev->active1 = *active;
+ if (!list_empty(&pcdev->capture)) {
+ active_buf = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
+ if (active_buf) {
+
+ WARN_ON(active_buf->state != VIDEOBUF_QUEUED);
+ if ((flag == 0) && ((active_buf->i)%2 == 0)){
+ pcdev->active0 = active_buf;
+ } else if ((flag == 1) && ((active_buf->i)%2 == 1)){
+ pcdev->active1 = active_buf;
}else{
- printk("irq frame status erro !\n");
+ RKCAMERA_DG1("irq frame status erro or no a suitable buf!\n");
+ goto end;
}
- rk_videobuf_capture((*active),pcdev,flag);
- list_del_init(&((*active)->queue));
- }
- }
- spin_unlock(&pcdev->lock);
- if ((*active) == NULL) {
- // RK30_CAM_DEBUG_TRACE("%s video_buf queue is empty!\n",__FUNCTION__);
- if(flag == 0){
- pcdev->active0 = NULL;
- write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, invalid_y_addr);
- write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, invalid_uv_addr);
- }else{
- pcdev->active1 = NULL;
- write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, invalid_y_addr);
- write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, invalid_uv_addr);
- }
- }
- if(vb)
- do_gettimeofday(&vb->ts);
- if (CAM_WORKQUEUE_IS_EN()) {
- if(vb){
- if (!list_empty(&pcdev->camera_work_queue)) {
- wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
- list_del_init(&wk->queue);
- INIT_WORK(&(wk->work), rk_camera_capture_process);
- wk->vb = vb;
- wk->pcdev = pcdev;
- wk->ts = pcdev->fps;
- queue_work(pcdev->camera_wq, &(wk->work));
- }else{
- printk("work queue is empty \n!!!!!!!!");
- }
- }
- } else {
- if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
- vb->state = VIDEOBUF_DONE;
- vb->field_count++;
- }
- wake_up(&vb->done);
- }
+ rk_videobuf_capture(active_buf,pcdev,flag);
+ list_del_init(&(active_buf->queue));
+ }
+ }else{
+ RKCAMERA_DG1("video_buf queue is empty!\n");
+ goto end;
+ }
+
+ do_gettimeofday(&vb->ts);
+ if (CAM_WORKQUEUE_IS_EN()) {
+ if (!list_empty(&pcdev->camera_work_queue)) {
+ wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
+ list_del_init(&wk->queue);
+ INIT_WORK(&(wk->work), rk_camera_capture_process);
+ wk->vb = vb;
+ wk->pcdev = pcdev;
+ queue_work(pcdev->camera_wq, &(wk->work));
+ }
+ } else {
+ if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
+ vb->state = VIDEOBUF_DONE;
+ vb->field_count++;
+ }
+ wake_up(&vb->done);
+ }
}
-first_frame_done:
- if ((tmp_cif_frmst & CIF_F0_READY) && (tmp_cif_frmst & CIF_F1_READY)){
- printk(KERN_DEBUG"%s:f0 && f1 ready ,need to process f1 too!!!!!\n",__func__);
- tmp_cif_frmst &=~CIF_F0_READY;
- goto process_another_frame;
- }
-RK_CAMERA_IRQ_END:
- if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
+end:
+ if((reg_cifctrl & ENABLE_CAPTURE) == 0)
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (reg_cifctrl | ENABLE_CAPTURE));
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rk_camera_irq(int irq, void *data)
+{
+ struct rk_camera_dev *pcdev = data;
+ unsigned long reg_intstat;
+
+
+ spin_lock(&pcdev->lock);
+
+ if(atomic_read(&pcdev->stop_cif) == true) {
+ write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xffffffff);
+ goto end;
+ }
+
+ reg_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s() ,reg_intstat 0x%lx\n", __FILE__, __LINE__,__FUNCTION__,reg_intstat);
+ if (reg_intstat & 0x0200)
+ rk_camera_cifirq(irq,data);
+
+ if (reg_intstat & 0x01)
+ rk_camera_dmairq(irq,data);
+
+end:
+ spin_unlock(&pcdev->lock);
return IRQ_HANDLED;
}
{
struct rk_camera_buffer *buf = container_of(vb, struct rk_camera_buffer, vb);
struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
#if CAMERA_VIDEOBUF_ARM_ACCESS
struct rk29_camera_vbinfo *vb_info =NULL;
#endif
#ifdef DEBUG
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
}
#endif
- #if 0 /* ddl@rock-chips.com: this wait operation is not nessary, invalidate in v0.x.1f */
- if (vb == pcdev->active0 || vb == pcdev->active1) {
- RK30_CAM_DEBUG_TRACE("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
- interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
- RK30_CAM_DEBUG_TRACE("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
- }
- #endif
- flush_workqueue(pcdev->camera_wq);
+ flush_workqueue(pcdev->camera_wq);
+
+ rk_videobuf_free(vq, buf);
+
#if CAMERA_VIDEOBUF_ARM_ACCESS
- if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) {
- vb_info = pcdev->vbinfo + vb->i;
+ if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) {
+ vb_info = pcdev->vbinfo + vb->i;
- if (vb_info->vir_addr) {
- iounmap(vb_info->vir_addr);
- release_mem_region(vb_info->phy_addr, vb_info->size);
- memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
- }
+ if (vb_info->vir_addr) {
+ iounmap(vb_info->vir_addr);
+ release_mem_region(vb_info->phy_addr, vb_info->size);
+ memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
+ }
+
}
-#endif
- rk_videobuf_free(vq, buf);
+#endif
}
static struct videobuf_queue_ops rk_videobuf_ops =
static void rk_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_device *icd)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
/* We must pass NULL as dev pointer, then all pci_* dma operations
* transform to normal dma_* ones. */
videobuf_queue_dma_contig_init(q,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
sizeof(struct rk_camera_buffer),
- icd,&icd->video_lock);
+ icd,&(ici->host_lock) );
}
-static int rk_camera_mclk_ctrl(int cif_idx, int on, int clk_rate){
- int err = 0,cif;
+static int rk_camera_mclk_ctrl(int cif_idx, int on, int clk_rate)
+{
+ int err = 0,cif;
struct rk_cif_clk *clk;
- struct clk *cif_clk_out_div;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
cif = cif_idx - RK29_CAM_PLATFORM_DEV_ID;
if ((cif<0)||(cif>1)) {
RKCAMERA_TR(KERN_ERR "cif index(%d) is invalidate\n",cif_idx);
err = -1;
goto rk_camera_clk_ctrl_end;
- }
+ }
clk = &cif_clk[cif];
-
+
if(!clk->aclk_cif || !clk->hclk_cif || !clk->cif_clk_in || !clk->cif_clk_out) {
RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
err = -ENOENT;
goto rk_camera_clk_ctrl_end;
}
- spin_lock(&clk->lock);
- if (on && !clk->on) {
- clk_enable(clk->pd_cif);
- clk_enable(clk->aclk_cif);
- clk_enable(clk->hclk_cif);
- clk_enable(clk->cif_clk_in);
- clk_enable(clk->cif_clk_out);
+
+ //spin_lock(&clk->lock);
+ if (on && !clk->on) {
+ clk_prepare_enable(clk->pd_cif); /*yzm*/
+ clk_prepare_enable(clk->aclk_cif);
+ clk_prepare_enable(clk->hclk_cif);
+ clk_prepare_enable(clk->cif_clk_in);
+ clk_prepare_enable(clk->cif_clk_out);
clk_set_rate(clk->cif_clk_out,clk_rate);
- mdelay(10);
clk->on = true;
-
} else if (!on && clk->on) {
- clk_disable(clk->aclk_cif);
- clk_disable(clk->hclk_cif);
- clk_disable(clk->cif_clk_in);
-
- clk_disable(clk->cif_clk_out);
- clk_disable(clk->pd_cif);
+ clk_set_rate(clk->cif_clk_out,36000000);/*yzm :just for close clk which base on XIN24M */
+ msleep(100);
+ clk_disable_unprepare(clk->aclk_cif);
+ clk_disable_unprepare(clk->hclk_cif);
+ clk_disable_unprepare(clk->cif_clk_in);
+ if(CHIP_NAME == 3126){
+ write_cru_reg(CRU_CLKSEL29_CON, 0x007c0000);
+ write_cru_reg(CRU_CLK_OUT, 0x00800080);
+ }
+ clk_disable_unprepare(clk->cif_clk_out);
+ clk_disable_unprepare(clk->pd_cif);
clk->on = false;
- if(cif){
- cif_clk_out_div = clk_get(NULL, "cif1_out_div");
- }else{
- cif_clk_out_div = clk_get(NULL, "cif0_out_div");
- if(IS_ERR_OR_NULL(cif_clk_out_div)) {
- cif_clk_out_div = clk_get(NULL, "cif_out_div");
- }
- }
-
- if(IS_ERR_OR_NULL(cif_clk_out_div)) {
- err = clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
- clk_put(cif_clk_out_div);
- } else {
- err = -1;
- }
-
- if(err)
- RKCAMERA_TR("WARNING %s_%s_%d: camera sensor mclk maybe not close, please check!!!\n", __FILE__, __FUNCTION__, __LINE__);
}
- spin_unlock(&clk->lock);
+ //spin_unlock(&clk->lock);
rk_camera_clk_ctrl_end:
return err;
}
static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
{
- write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_PINGPONG|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
+ /*
+ * ddl@rock-chips.com : Cif clk control in rk_sensor_power which in rk_camera.c
+ */
- write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
- RK30_CAM_DEBUG_TRACE("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_PINGPONG|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
+ //write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
return 0;
-RK_CAMERA_ACTIVE_ERR:
- return -ENODEV;
}
static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
-{
+{
+ /*
+ * ddl@rock-chips.com : Cif clk control in rk_sensor_power which in rk_camera.c
+ */
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+
return;
}
* there can be only one camera on RK28 quick capture interface */
static int rk_camera_add_device(struct soc_camera_device *icd)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct rk_camera_dev *pcdev = ici->priv;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
+ struct rk_camera_dev *pcdev = ici->priv; /*Initialize in rk_camra_prob*/
struct device *control = to_soc_camera_control(icd);
struct v4l2_subdev *sd;
int ret,i,icd_catch;
struct v4l2_cropcap cropcap;
struct v4l2_mbus_framefmt mf;
const struct soc_camera_format_xlate *xlate = NULL;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
mutex_lock(&camera_lock);
goto ebusy;
}
- RK30_CAM_DEBUG_TRACE("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
+ RKCAMERA_DG1("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
+ //pcdev->active = NULL;
pcdev->active0 = NULL;
pcdev->active1 = NULL;
+ pcdev->active_buf = 0;
pcdev->icd = NULL;
pcdev->reginfo_suspend.Inval = Reg_Invalidate;
pcdev->zoominfo.zoom_rate = 100;
if (ret)
goto ebusy;
/* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
- if (control) {
+ if (control) { //TRUE in open ,FALSE in kernel start
sd = dev_get_drvdata(control);
v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
#if 0
if (ret)
goto ebusy;
#endif
+ /* call generic_sensor_ioctl*/
v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
-
+ /* call generic_sensor_cropcap*/
if (v4l2_subdev_call(sd, video, cropcap, &cropcap) == 0) {
memcpy(&pcdev->cropinfo.bounds ,&cropcap.bounds,sizeof(struct v4l2_rect));
} else {
pcdev->cropinfo.bounds.height = mf.height;
}
}
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
pcdev->icd = icd;
pcdev->icd_init = 0;
-
+
icd_catch = 0;
for (i=0; i<2; i++) {
if (pcdev->icd_frmival[i].icd == icd)
}
static void rk_camera_remove_device(struct soc_camera_device *icd)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ /*struct v4l2_subdev *sd = soc_camera_to_subdev(icd);*/
#if CAMERA_VIDEOBUF_ARM_ACCESS
struct rk29_camera_vbinfo *vb_info;
unsigned int i;
-#endif
+#endif
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
mutex_lock(&camera_lock);
BUG_ON(icd != pcdev->icd);
- RK30_CAM_DEBUG_TRACE("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
-
- /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
+ RKCAMERA_DG1("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
+
+ /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
stream may be turn on again before close device, if suspend and resume happened. */
- if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
+ /*if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {*/
+ if ((atomic_read(&pcdev->stop_cif) == false) && pcdev->fps_timer.istarted) { /* ddl@rock-chips.com: v0.3.0x15*/
rk_camera_s_stream(icd,0);
- }
-
- //soft reset the registers
- #if 0 //has somthing wrong when suspend and resume now
- if(IS_CIF0()){
- write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF0|RQUEST_RST_CIF0 | (read_cru_reg(CRU_CIF_RST_REG30)));
- write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
- }else{
- write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
- write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
- }
- #endif
- v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
- //if stream off is not been executed,timer is running.
+ }
+ /* move DEACTIVATE into generic_sensor_s_power*/
+ /* v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);*/ /*yzm*/
+ /* if stream off is not been executed,timer is running.*/
if(pcdev->fps_timer.istarted){
hrtimer_cancel(&pcdev->fps_timer.timer);
pcdev->fps_timer.istarted = false;
pcdev->vbinfo_count = 0;
}
#endif
- pcdev->active0 = NULL;
+ //pcdev->active = NULL;
+ pcdev->active0 = NULL;
pcdev->active1 = NULL;
+ pcdev->active_buf = 0;
pcdev->icd = NULL;
pcdev->icd_cb.sensor_cb = NULL;
pcdev->reginfo_suspend.Inval = Reg_Invalidate;
INIT_LIST_HEAD(&pcdev->capture);
mutex_unlock(&camera_lock);
- RK30_CAM_DEBUG_TRACE("%s exit\n",__FUNCTION__);
return;
}
static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
{
- unsigned long bus_flags, camera_flags, common_flags;
- unsigned int cif_ctrl_val = 0;
+ unsigned long bus_flags, camera_flags, common_flags = 0;
+ unsigned int cif_for = 0;
const struct soc_mbus_pixelfmt *fmt;
int ret = 0;
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); /*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
- RK30_CAM_DEBUG_TRACE("%s..%d..\n",__FUNCTION__,__LINE__);
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
if (!fmt)
default:
return -EINVAL;
}
-
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
if (icd->ops->query_bus_param)
camera_flags = icd->ops->query_bus_param(icd);
else
camera_flags = 0;
+/**************yzm************
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
if (!common_flags) {
ret = -EINVAL;
goto RK_CAMERA_SET_BUS_PARAM_END;
}
+*/
+/***************yzm************end*/
+
+ common_flags = camera_flags;
ret = icd->ops->set_bus_param(icd, common_flags);
if (ret < 0)
goto RK_CAMERA_SET_BUS_PARAM_END;
- cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
- RK30_CAM_DEBUG_TRACE("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
- if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
+ cif_for = read_cif_reg(pcdev->base,CIF_CIF_FOR);
+
+ if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) {
if(IS_CIF0()) {
write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
- RK30_CAM_DEBUG_TRACE("enable cif0 pclk invert\n");
} else {
write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
- RK30_CAM_DEBUG_TRACE("enable cif1 pclk invert\n");
}
} else {
if(IS_CIF0()){
write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
- RK30_CAM_DEBUG_TRACE("diable cif0 pclk invert\n");
} else {
write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
- RK30_CAM_DEBUG_TRACE("diable cif1 pclk invert\n");
}
}
- if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
- cif_ctrl_val |= HSY_LOW_ACTIVE;
+
+ if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) {
+ cif_for |= HSY_LOW_ACTIVE;
} else {
- cif_ctrl_val &= ~HSY_LOW_ACTIVE;
+ cif_for &= ~HSY_LOW_ACTIVE;
}
- if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
- cif_ctrl_val |= VSY_HIGH_ACTIVE;
+ if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) {
+ cif_for |= VSY_HIGH_ACTIVE;
} else {
- cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
+ cif_for &= ~VSY_HIGH_ACTIVE;
}
- /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
+ // ddl@rock-chips.com : Don't enable capture here, enable in stream_on
//vip_ctrl_val |= ENABLE_CAPTURE;
- write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
- RK30_CAM_DEBUG_TRACE("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
+ write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_for);
+ RKCAMERA_DG1("CIF_CIF_FOR: 0x%x \n",cif_for);
RK_CAMERA_SET_BUS_PARAM_END:
if (ret)
- RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
+ RKCAMERA_TR("rk_camera_set_bus_param ret = %d \n", ret);
return ret;
}
static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
{
- unsigned long bus_flags, camera_flags;
- int ret;
+/* unsigned long bus_flags, camera_flags;*/
+/* int ret;*/
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+/**********yzm***********
bus_flags = RK_CAM_BUS_PARAM;
if (icd->ops->query_bus_param) {
- camera_flags = icd->ops->query_bus_param(icd);
+ camera_flags = icd->ops->query_bus_param(icd); //generic_sensor_query_bus_param()
} else {
camera_flags = 0;
}
ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
- /* rockchip BUGBUG
- if (ret < 0)
- dev_warn(icd->dev.parent,
- "Flags incompatible: camera %lx, host %lx\n",
- camera_flags, bus_flags);
- */
- if(!ret){
- dev_warn(icd->dev.parent, "Flags incompatible: camera %lx, host %lx\n", camera_flags, bus_flags);
- ret = -EINVAL;
- }
- else{
- ret = 0;
- }
+ if (ret < 0)
+ dev_warn(icd->dev.parent,
+ "Flags incompatible: camera %lx, host %lx\n",
+ camera_flags, bus_flags);
+
return ret;
+*///************yzm **************end
+ return 0;
+
}
static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
.packing = SOC_MBUS_PACKING_2X8_PADHI,
.order = SOC_MBUS_ORDER_LE,
}
+
};
static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
unsigned int cif_fs = 0,cif_crop = 0;
unsigned int cif_fmt_val = read_cif_reg(pcdev->base,CIF_CIF_FOR) | INPUT_MODE_YUV|YUV_INPUT_422|INPUT_420_ORDER_EVEN|OUTPUT_420_ORDER_EVEN;
const struct soc_mbus_pixelfmt *fmt;
fmt = soc_mbus_get_fmtdesc(icd_code);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){
if(fmt->fourcc == V4L2_PIX_FMT_NV12)
host_pixfmt = V4L2_PIX_FMT_NV12;
cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
break;
}
-#if 1
- {
-#if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928))
- mdelay(100);
- if(IS_CIF0()){
- // pmu_set_idle_request(IDLE_REQ_VIO, true);
- cru_set_soft_reset(SOFT_RST_CIF0, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF0, false);
- // pmu_set_idle_request(IDLE_REQ_VIO, false);
-
- }else{
- // pmu_set_idle_request(IDLE_REQ_VIO, true);
- cru_set_soft_reset(SOFT_RST_CIF1, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF1, false);
- // pmu_set_idle_request(IDLE_REQ_VIO, false);
- }
-#elif defined(CONFIG_ARCH_RK3188)
-// pmu_set_idle_request(IDLE_REQ_VIO, true);
- cru_set_soft_reset(SOFT_RST_CIF0, true);
- udelay(5);
- cru_set_soft_reset(SOFT_RST_CIF0, false);
-// pmu_set_idle_request(IDLE_REQ_VIO, false);
-#endif
- }
+ mdelay(100);
+ rk_camera_cif_reset(pcdev,true);
+
write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_PINGPONG|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
- write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
-#endif
+ //write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); /*capture complete interrupt enable*/
+
write_cif_reg(pcdev->base,CIF_CIF_FOR,cif_fmt_val); /* ddl@rock-chips.com: VIP capture mode and capture format must be set before FS register set */
- // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); /* clear vip interrupte single */
- write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
- /*
- if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
+ write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
+ /*if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
BUG();
- } else*/{ // this is one frame mode
- cif_crop = (rect->left+ (rect->top<<16));
- cif_fs = ((rect->width ) + (rect->height<<16));
+ } else*/{ /* this is one frame mode*/
+ cif_crop = (rect->left + (rect->top <<16));
+ cif_fs = (rect->width + (rect->height <<16));
}
write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
- //MUST bypass scale
+ /*MUST bypass scale */
write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
- RK30_CAM_DEBUG_TRACE("%s.. crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",__FUNCTION__,cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
+ RKCAMERA_DG1("CIF_CIF_CROP:0x%x CIF_CIF_FS:0x%x CIF_CIF_FOR:0x%x\n",cif_crop,cif_fs,cif_fmt_val);
return;
}
struct soc_camera_format_xlate *xlate)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct device *dev = icd->dev.parent;
+ struct device *dev = icd->parent;/*yzm*/
int formats = 0, ret;
enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
+ ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); /*call generic_sensor_enum_fmt()*/
if (ret < 0)
/* No more formats */
return 0;
return 0;
switch (code) {
- case V4L2_MBUS_FMT_UYVY8_2X8:
- case V4L2_MBUS_FMT_YUYV8_2X8:
- case V4L2_MBUS_FMT_YVYU8_2X8:
- case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ {
+
#if (CONFIG_CAMERA_SCALE_CROP_MACHINE != RK_CAM_SCALE_CROP_RGA)
- formats++;
- if (xlate) {
- xlate->host_fmt = &rk_camera_formats[0];
- xlate->code = code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code %d\n",
- rk_camera_formats[0].name,code);
- }
-
- formats++;
- if (xlate) {
- xlate->host_fmt = &rk_camera_formats[1];
- xlate->code = code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code %d\n",
- rk_camera_formats[1].name,code);
- }
-
- formats++;
- if (xlate) {
- xlate->host_fmt = &rk_camera_formats[2];
- xlate->code = code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code %d\n",
- rk_camera_formats[2].name,code);
- }
-
- formats++;
- if (xlate) {
- xlate->host_fmt = &rk_camera_formats[3];
- xlate->code = code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code %d\n",
- rk_camera_formats[3].name,code);
- }
- break;
+ formats++;
+ if (xlate) {
+ xlate->host_fmt = &rk_camera_formats[0];
+ xlate->code = code;
+ xlate++;
+ dev_dbg(dev, "Providing format %s using code %d\n",
+ rk_camera_formats[0].name,code);
+ }
+
+ formats++;
+ if (xlate) {
+ xlate->host_fmt = &rk_camera_formats[1];
+ xlate->code = code;
+ xlate++;
+ dev_dbg(dev, "Providing format %s using code %d\n",
+ rk_camera_formats[1].name,code);
+ }
+
+ formats++;
+ if (xlate) {
+ xlate->host_fmt = &rk_camera_formats[2];
+ xlate->code = code;
+ xlate++;
+ dev_dbg(dev, "Providing format %s using code %d\n",
+ rk_camera_formats[2].name,code);
+ }
+
+ formats++;
+ if (xlate) {
+ xlate->host_fmt = &rk_camera_formats[3];
+ xlate->code = code;
+ xlate++;
+ dev_dbg(dev, "Providing format %s using code %d\n",
+ rk_camera_formats[3].name,code);
+ }
+ break;
#else
- formats++;
- if (xlate) {
- xlate->host_fmt = &rk_camera_formats[4];
- xlate->code = code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code %d\n",
- rk_camera_formats[4].name,code);
- }
- formats++;
- if (xlate) {
- xlate->host_fmt = &rk_camera_formats[5];
- xlate->code = code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code %d\n",
- rk_camera_formats[5].name,code);
- }
+ formats++;
+ if (xlate) {
+ xlate->host_fmt = &rk_camera_formats[4];
+ xlate->code = code;
+ xlate++;
+ dev_dbg(dev, "Providing format %s using code %d\n",
+ rk_camera_formats[4].name,code);
+ }
+ formats++;
+ if (xlate) {
+ xlate->host_fmt = &rk_camera_formats[5];
+ xlate->code = code;
+ xlate++;
+ dev_dbg(dev, "Providing format %s using code %d\n",
+ rk_camera_formats[5].name,code);
+ }
break;
#endif
+ }
default:
break;
}
static void rk_camera_put_formats(struct soc_camera_device *icd)
{
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
return;
}
+static int rk_camera_cropcap(struct soc_camera_device *icd, struct v4l2_cropcap *cropcap)
+{
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ int ret=0;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+ ret = v4l2_subdev_call(sd, video, cropcap, cropcap);
+ if (ret != 0)
+ goto end;
+ /* ddl@rock-chips.com: driver decide the cropping rectangle */
+ memset(&cropcap->defrect,0x00,sizeof(struct v4l2_rect));
+end:
+ return ret;
+}
static int rk_camera_get_crop(struct soc_camera_device *icd,struct v4l2_crop *crop)
{
- struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
spin_lock(&pcdev->cropinfo.lock);
memcpy(&crop->c,&pcdev->cropinfo.c,sizeof(struct v4l2_rect));
spin_unlock(&pcdev->cropinfo.lock);
return 0;
}
static int rk_camera_set_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+ const struct v4l2_crop *crop)
{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
- u32 fourcc = icd->current_fmt->host_fmt->fourcc;
- int ret;
-
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
- if (ret < 0)
- return ret;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
+ struct rk_camera_dev *pcdev = ici->priv;
- if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
- mf.width = a->c.left + a->c.width;
- mf.height = a->c.top + a->c.height;
- v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
- &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
- fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
+ spin_lock(&pcdev->cropinfo.lock);
+ memcpy(&pcdev->cropinfo.c,&crop->c,sizeof(struct v4l2_rect));
+ spin_unlock(&pcdev->cropinfo.lock);
+ return 0;
+}
+static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
+{
+ bool ret = false;
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
- if (ret < 0)
- return ret;
- }
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
- rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
- icd->user_width = mf.width;
- icd->user_height = mf.height;
+ if (f->fmt.pix.priv == 0xfefe5a5a) {
+ ret = true;
+ }
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
+ ret = true;
+ }
- return 0;
+ if (ret == true)
+ RKCAMERA_DG1("%dx%d is capture format\n",f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
}
-
static int rk_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct device *dev = icd->dev.parent;
+ struct device *dev = icd->parent;/*yzm*/
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate = NULL;
- struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_mbus_framefmt mf;
int ret,usr_w,usr_h,sensor_w,sensor_h;
int stream_on = 0;
int ratio, bounds_aspect;
-
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
usr_w = pix->width;
usr_h = pix->height;
- RK30_CAM_DEBUG_TRACE("enter width:%d height:%d\n",usr_w,usr_h);
+ RKCAMERA_DG1("enter width:%d height:%d\n",usr_w,usr_h);
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
dev_err(dev, "Format %x not found\n", pix->pixelformat);
/* ddl@rock-chips.com: sensor init code transmit in here after open */
if (pcdev->icd_init == 0) {
- v4l2_subdev_call(sd,core, init, 0);
+ v4l2_subdev_call(sd,core, init, 0); /*call generic_sensor_init()*/
pcdev->icd_init = 1;
- return 0;
+ return 0; /*directly return !!!!!!*/
}
stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
if (stream_on & ENABLE_CAPTURE)
mf.reserved[0] = pix->priv; /* ddl@rock-chips.com : v0.3.3 */
mf.reserved[1] = 0;
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); /*generic_sensor_s_fmt*/
if (mf.code != xlate->code)
return -EINVAL;
(pcdev->cropinfo.c.height == pcdev->cropinfo.bounds.height)) {
bounds_aspect = (pcdev->cropinfo.bounds.width*10/pcdev->cropinfo.bounds.height);
if ((mf.width*10/mf.height) != bounds_aspect) {
- RK30_CAM_DEBUG_TRACE("User request fov unchanged in %dx%d, But sensor %dx%d is croped, so switch to full resolution %dx%d\n",
+ RKCAMERA_DG1("User request fov unchanged in %dx%d, But sensor %dx%d is croped, so switch to full resolution %dx%d\n",
usr_w,usr_h,mf.width, mf.height,pcdev->cropinfo.bounds.width,pcdev->cropinfo.bounds.height);
mf.width = pcdev->cropinfo.bounds.width/4;
sensor_w = mf.width;
sensor_h = mf.height;
- ratio = ((mf.width*mf.reserved[1])/100)&(~0x03); // 4 align
+ ratio = ((mf.width*mf.reserved[1])/100)&(~0x03); /* 4 align*/
mf.width -= ratio;
- ratio = ((ratio*mf.height/mf.width)+1)&(~0x01); // 2 align
+ ratio = ((ratio*mf.height/mf.width)+1)&(~0x01); /* 2 align*/
mf.height -= ratio;
if ((mf.width != usr_w) || (mf.height != usr_h)) {
spin_lock(&pcdev->cropinfo.lock);
if (((mf.width*10/mf.height) != (usr_w*10/usr_h))) {
if ((pcdev->cropinfo.c.width == 0)&&(pcdev->cropinfo.c.height == 0)) {
- //Scale + Crop center is for keep aspect ratio unchange
+ /*Scale + Crop center is for keep aspect ratio unchange*/
ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
pcdev->host_width = ratio*usr_w/10;
pcdev->host_height = ratio*usr_h/10;
pcdev->host_left = ((sensor_w-pcdev->host_width )>>1);
pcdev->host_top = ((sensor_h-pcdev->host_height)>>1);
} else {
- //Scale + crop(user define)
+ /*Scale + crop(user define)*/
pcdev->host_width = pcdev->cropinfo.c.width*mf.width/pcdev->cropinfo.bounds.width;
pcdev->host_height = pcdev->cropinfo.c.height*mf.height/pcdev->cropinfo.bounds.height;
pcdev->host_left = (pcdev->cropinfo.c.left*mf.width/pcdev->cropinfo.bounds.width);
pcdev->host_top &= (~0x01);
} else {
if ((pcdev->cropinfo.c.width == 0)&&(pcdev->cropinfo.c.height == 0)) {
- //Crop Center for cif can work , then scale
+ /*Crop Center for cif can work , then scale*/
pcdev->host_width = mf.width;
pcdev->host_height = mf.height;
pcdev->host_left = ((sensor_w - mf.width)>>1)&(~0x01);
pcdev->host_top = ((sensor_h - mf.height)>>1)&(~0x01);
} else {
- //Crop center for cif can work + crop(user define), then scale
+ /*Crop center for cif can work + crop(user define), then scale */
pcdev->host_width = pcdev->cropinfo.c.width*mf.width/pcdev->cropinfo.bounds.width;
pcdev->host_height = pcdev->cropinfo.c.height*mf.height/pcdev->cropinfo.bounds.height;
pcdev->host_left = (pcdev->cropinfo.c.left*mf.width/pcdev->cropinfo.bounds.width)+((sensor_w - mf.width)>>1);
rect.top = pcdev->host_top;
down(&pcdev->zoominfo.sem);
-#if CIF_DO_CROP // this crop is only for digital zoom
+#if CIF_DO_CROP /* this crop is only for digital zoom*/
pcdev->zoominfo.a.c.left = 0;
pcdev->zoominfo.a.c.top = 0;
pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
- //recalculate the CIF width & height
+ /*recalculate the CIF width & height*/
rect.width = pcdev->zoominfo.a.c.width ;
rect.height = pcdev->zoominfo.a.c.height;
rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
- //now digital zoom use ipp to do crop and scale
+ /*now digital zoom use ipp to do crop and scale*/
if(pcdev->zoominfo.zoom_rate != 100){
pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
}
}
- RK30_CAM_DEBUG_TRACE("%s CIF Host:%dx%d@(%d,%d) Sensor:%dx%d->%dx%d User crop:(%d,%d,%d,%d)in(%d,%d) (zoom: %dx%d@(%d,%d)->%dx%d)\n",xlate->host_fmt->name,
+ RKCAMERA_DG1("%s CIF Host:%dx%d@(%d,%d) Sensor:%dx%d->%dx%d User crop:(%d,%d,%d,%d)in(%d,%d) (zoom: %dx%d@(%d,%d)->%dx%d)\n",xlate->host_fmt->name,
pcdev->host_width,pcdev->host_height,pcdev->host_left,pcdev->host_top,
sensor_w,sensor_h,mf.width,mf.height,
pcdev->cropinfo.c.left,pcdev->cropinfo.c.top,pcdev->cropinfo.c.width,pcdev->cropinfo.c.height,
pcdev->cropinfo.bounds.width,pcdev->cropinfo.bounds.height,
pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
pix->width, pix->height);
+
rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
if (CAM_IPPWORK_IS_EN()) {
RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
return ret;
}
-static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
-{
- bool ret = false;
-
- if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
- ret = true;
- } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
- ret = true;
- } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
- ret = true;
- } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
- ret = true;
- } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
- ret = true;
- } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
- ret = true;
- }
- if (ret == true)
- RK30_CAM_DEBUG_TRACE("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
- return ret;
-}
static int rk_camera_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
__u32 pixfmt = pix->pixelformat;
int ret,usr_w,usr_h,i;
- bool is_capture = rk_camera_fmt_capturechk(f);
+ bool is_capture = rk_camera_fmt_capturechk(f); /* testing f is in line with the already set*/
bool vipmem_is_overflow = false;
struct v4l2_mbus_framefmt mf;
int bytes_per_line_host;
usr_w = pix->width;
usr_h = pix->height;
- xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
+ /*dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,*/
+ dev_err(icd->parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,/*yzm*/
(pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
ret = -EINVAL;
- RK30_CAM_DEBUG_TRACE("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
+ RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
(RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
for (i = 0; i < icd->num_user_formats; i++)
- RK30_CAM_DEBUG_TRACE("(%c%c%c%c)-%s\n",
+ RKCAMERA_TR("(%c%c%c%c)-%s\n",
icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
(icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
icd->user_formats[i].host_fmt->name);
if ((usr_w == 10000) && (usr_h == 10000)) {
mf.reserved[6] = 0xfefe5a5a;
}
-
+ /* call generic_sensor_try_fmt()*/
ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
if (ret < 0)
goto RK_CAMERA_TRY_FMT_END;
- //query resolution.
+ /*query resolution.*/
if((usr_w == 10000) && (usr_h == 10000)) {
pix->width = mf.width;
pix->height = mf.height;
- RK30_CAM_DEBUG_TRACE("%s: Sensor resolution : %dx%d\n",__FUNCTION__,mf.width,mf.height);
+ RKCAMERA_DG1("Sensor resolution : %dx%d\n",mf.width,mf.height);
goto RK_CAMERA_TRY_FMT_END;
} else {
- RK30_CAM_DEBUG_TRACE("%s: user demand: %dx%d sensor output: %dx%d \n",__FUNCTION__,usr_w,usr_h,mf.width,mf.height);
- }
-
- #ifdef CONFIG_VIDEO_RK29_WORK_IPP
+ RKCAMERA_DG1("user demand: %dx%d sensor output: %dx%d \n",usr_w,usr_h,mf.width,mf.height);
+ }
+
if ((mf.width != usr_w) || (mf.height != usr_h)) {
bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
- #ifndef OPTIMIZE_MEMORY_USE
if (is_capture) {
vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
} else {
/* Assume preview buffer minimum is 4 */
vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
- }
- #else
- vipmem_is_overflow =false;
- #endif
+ }
if (vipmem_is_overflow == false) {
pix->width = usr_w;
pix->height = usr_h;
} else {
- RK30_CAM_DEBUG_TRACE("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
+ /*RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);*/ /*yzm*/
pix->width = mf.width;
pix->height = mf.height;
}
#if 0
if ((mf.width < usr_w) || (mf.height < usr_h)) {
if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
- RK30_CAM_DEBUG_TRACE("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
+ RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
pix->width = mf.width;
pix->height = mf.height;
}
}
#endif
}
- #else
- //need to change according to crop and scale capablicity
- if ((mf.width > usr_w) && (mf.height > usr_h)) {
- pix->width = usr_w;
- pix->height = usr_h;
- } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
- RK30_CAM_DEBUG_TRACE("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
- pix->width = mf.width;
- pix->height = mf.height;
- }
- #endif
+
pix->colorspace = mf.colorspace;
switch (mf.field) {
break;
default:
/* TODO: support interlaced at least in pass-through mode */
- dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+ dev_err(icd->parent, "Field type %d unsupported.\n",
mf.field);
goto RK_CAMERA_TRY_FMT_END;
}
RK_CAMERA_TRY_FMT_END:
- if (ret)
- RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
+ if (ret<0)
+ RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
return ret;
}
{
int i;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
/* This is for locking debugging only. I removed spinlocks and now I
* check whether .prepare is ever called on a linked buffer, or whether
* a dma IRQ can occur for an in-work or unlinked buffer. Until now
struct soc_camera_device *icd = file->private_data;
struct rk_camera_buffer *buf;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
vb.stream);
return 0;
}
+/*
+*card: sensor name _ facing _ device index - orientation _ fov horizontal _ fov vertical
+* 10 5 1 3 3 3 + 5 < 32
+*/
static int rk_camera_querycap(struct soc_camera_host *ici,
struct v4l2_capability *cap)
char fov[9];
int i;
- strlcpy(cap->card, dev_name(pcdev->icd->pdev), 20);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+
+ strlcpy(cap->card, dev_name(pcdev->icd->pdev), 18);
memset(orientation,0x00,sizeof(orientation));
- for (i=0; i<RK_CAM_NUM;i++) {
- if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
- sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
- sprintf(fov,"_50_50");
- }
- }
i=0;
new_camera = pcdev->pdata->register_dev_new;
- while (strstr(new_camera->dev_name,"end")==NULL) {
+ while(new_camera != NULL){
if (strcmp(dev_name(pcdev->icd->pdev), new_camera->dev_name) == 0) {
sprintf(orientation,"-%d",new_camera->orientation);
sprintf(fov,"_%d_%d",new_camera->fov_h,new_camera->fov_v);
}
- new_camera++;
+ new_camera = new_camera->next_camera;
}
-
+
if (orientation[0] != '-') {
RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
- if (strstr(dev_name(pcdev->icd->pdev),"front"))
+ if (strstr(dev_name(pcdev->icd->pdev),"front"))
strcat(cap->card,"-270");
- else
+ else
strcat(cap->card,"-90");
} else {
- strcat(cap->card,orientation);
+ strcat(cap->card,orientation);
}
-
+
strcat(cap->card,fov); /* ddl@rock-chips.com: v0.3.f */
cap->version = RK_CAM_VERSION_CODE;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
return 0;
}
static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
{
- struct soc_camera_host *ici =
- to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
struct v4l2_subdev *sd;
int ret = 0;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
mutex_lock(&camera_lock);
if ((pcdev->icd == icd) && (icd->ops->suspend)) {
rk_camera_s_stream(icd, 0);
pcdev->reginfo_suspend.Inval = Reg_Validate;
rk_camera_deactivate(pcdev);
- RK30_CAM_DEBUG_TRACE("%s Enter Success...\n", __FUNCTION__);
+ RKCAMERA_DG1("%s Enter Success...\n", __FUNCTION__);
} else {
- RK30_CAM_DEBUG_TRACE("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
+ RKCAMERA_DG1("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
}
mutex_unlock(&camera_lock);
return ret;
static int rk_camera_resume(struct soc_camera_device *icd)
{
- struct soc_camera_host *ici =
- to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
struct v4l2_subdev *sd;
int ret = 0;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
mutex_lock(&camera_lock);
if ((pcdev->icd == icd) && (icd->ops->resume)) {
if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
+ //rk_videobuf_capture(pcdev->active,pcdev);
rk_videobuf_capture(pcdev->active0,pcdev,0);
- rk_videobuf_capture(pcdev->active0,pcdev,1);
+ rk_videobuf_capture(pcdev->active1,pcdev,1);
rk_camera_s_stream(icd, 1);
pcdev->reginfo_suspend.Inval = Reg_Invalidate;
} else {
- RK30_CAM_DEBUG_TRACE("Resume fail, vip register recored is invalidate!!\n");
+ RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
goto rk_camera_resume_end;
}
sd = soc_camera_to_subdev(icd);
v4l2_subdev_call(sd, video, s_stream, 1);
- RK30_CAM_DEBUG_TRACE("%s Enter success\n",__FUNCTION__);
+ RKCAMERA_DG1("%s Enter success\n",__FUNCTION__);
} else {
- RK30_CAM_DEBUG_TRACE("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
+ RKCAMERA_DG1("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
}
rk_camera_resume_end:
struct v4l2_subdev *sd;
struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
struct rk_camera_dev *pcdev = camera_work->pcdev;
- struct soc_camera_link *tmp_soc_cam_link;
+ /*struct soc_camera_link *tmp_soc_cam_link;*/
+ struct v4l2_mbus_framefmt mf;
int index = 0;
unsigned long flags = 0;
+ int ctrl;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+ //return;
+
if(pcdev->icd == NULL)
return;
sd = soc_camera_to_subdev(pcdev->icd);
- tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
- //dump regs
+ /*tmp_soc_cam_desc = to_soc_camera_link(pcdev->icd);*/ /*yzm*/
+ /*dump regs*/
{
- RK30_CAM_DEBUG_TRACE("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
- RK30_CAM_DEBUG_TRACE("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
+ RKCAMERA_TR("CIF_CIF_CTRL = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
+ RKCAMERA_TR("CIF_CIF_INTEN = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
+ RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
+ RKCAMERA_TR("CIF_CIF_FOR = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
+ RKCAMERA_TR("CIF_CIF_CROP = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
+ RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
+ RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%lx\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
+ RKCAMERA_TR("CRU_PCLK_REG30 = 0X%lx\n",read_cru_reg(CRU_PCLK_REG30));
+ RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
- RK30_CAM_DEBUG_TRACE("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
+ RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
+ RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
+ RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
+ RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
+ RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
+ RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
+ RKCAMERA_TR("CIF_CIF_SCL_VALID_NUM = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_VALID_NUM));
+ RKCAMERA_TR("CIF_CIF_CUR_DST = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_CUR_DST));
+ RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%lx\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
}
- return;
- pcdev->stop_cif = true;
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
- RK30_CAM_DEBUG_TRACE("the reinit times = %d\n",pcdev->reinit_times);
- if(pcdev->video_vq && pcdev->video_vq->irqlock){
- spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
- for (index = 0; index < VIDEO_MAX_FRAME; index++) {
- if (NULL == pcdev->video_vq->bufs[index])
- continue;
+
+ ctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL); /*ddl@rock-chips.com v0.3.0x13*/
+ if (pcdev->reinit_times == 1) {
+ if (ctrl & ENABLE_CAPTURE) {
+ RKCAMERA_TR("Sensor data transfer may be error, so reset CIF and reinit sensor for resume!\n");
+ pcdev->irqinfo.cifirq_idx = pcdev->irqinfo.dmairq_idx;
+ rk_camera_cif_reset(pcdev,false);
+
+
+ v4l2_subdev_call(sd,core, init, 0);
+
+ mf.width = pcdev->icd_width;
+ mf.height = pcdev->icd_height;
+ mf.field = V4L2_FIELD_NONE;
+ mf.code = pcdev->icd->current_fmt->code;
+ mf.reserved[0] = 0x5a5afefe;
+ mf.reserved[1] = 0;
+
+ v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
- if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED)
- {
- list_del_init(&pcdev->video_vq->bufs[index]->queue);
- pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
- wake_up_all(&pcdev->video_vq->bufs[index]->done);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)|ENABLE_CAPTURE));
+ } else if (pcdev->irqinfo.cifirq_idx != pcdev->irqinfo.dmairq_idx) {
+ RKCAMERA_TR("CIF may be error, so reset cif for resume\n");
+ pcdev->irqinfo.cifirq_idx = pcdev->irqinfo.dmairq_idx;
+ rk_camera_cif_reset(pcdev,false);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)|ENABLE_CAPTURE));
+ }
+ return;
+ }
+
+ atomic_set(&pcdev->stop_cif,true);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
+ RKCAMERA_DG1("the reinit times = %d\n",pcdev->reinit_times);
+
+ if(pcdev->video_vq && pcdev->video_vq->irqlock){
+ spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
+ for (index = 0; index < VIDEO_MAX_FRAME; index++) {
+ if (NULL == pcdev->video_vq->bufs[index])
+ continue;
+
+ if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED) {
+ list_del_init(&pcdev->video_vq->bufs[index]->queue);
+ pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
+ wake_up_all(&pcdev->video_vq->bufs[index]->done);
printk("wake up video buffer index = %d !!!\n",index);
- }
- }
- spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
+ }
+ }
+ spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
}else{
- RK30_CAM_DEBUG_TRACE("video queue has somthing wrong !!\n");
+ RKCAMERA_TR("video queue has somthing wrong !!\n");
}
- RK30_CAM_DEBUG_TRACE("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
+ RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
}
static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
{
struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
struct rk_camera_dev *pcdev = fps_timer->pcdev;
int rec_flag,i;
- // static unsigned int last_fps = 0;
- struct soc_camera_link *tmp_soc_cam_link;
- tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
+ /*static unsigned int last_fps = 0;*/
+ /*struct soc_camera_link *tmp_soc_cam_link;*/ /*yzm*/
+ /*tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);*/ /*yzm*/
- RK30_CAM_DEBUG_TRACE("rk_camera_fps_func fps:%d\n",(pcdev->fps - pcdev->last_fps)/3);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+ RKCAMERA_DG1("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
- RK30_CAM_DEBUG_TRACE("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps);
+ RKCAMERA_TR("Camera host haven't recevie data from sensor,last fps = %d,pcdev->fps = %d,cif_irq: %ld,dma_irq: %ld!\n",
+ pcdev->last_fps,pcdev->fps,pcdev->irqinfo.cifirq_idx, pcdev->irqinfo.dmairq_idx);
pcdev->camera_reinit_work.pcdev = pcdev;
- //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
+ /*INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);*/
pcdev->reinit_times++;
- queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
+ queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));//Æô¶¯¹¤×÷¶ÓÁжÔÓ¦µÄº¯Êý
} else if(!pcdev->timer_get_fps) {
pcdev->timer_get_fps = true;
for (i=0; i<2; i++) {
fival_pre = fival_nxt;
while (fival_nxt != NULL) {
- RK30_CAM_DEBUG_TRACE("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
+ RKCAMERA_DG1("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(pcdev->icd->control), /*yzm*/
fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
(fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
}
}
}
+
+ if ((pcdev->last_fps != pcdev->fps) && (pcdev->reinit_times)) /*ddl@rock-chips.com v0.3.0x13*/
+ pcdev->reinit_times = 0;
+
pcdev->last_fps = pcdev->fps ;
pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
- //return HRTIMER_NORESTART;
+ /*return HRTIMER_NORESTART;*/
if(pcdev->reinit_times >=2)
return HRTIMER_NORESTART;
else
}
static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct rk_camera_dev *pcdev = ici->priv;
- int cif_ctrl_val;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
+ struct rk_camera_dev *pcdev = ici->priv;
+ int cif_ctrl_val;
int ret;
unsigned long flags;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
WARN_ON(pcdev->icd != icd);
cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
if (enable) {
pcdev->fps = 0;
- pcdev->last_fps = 0;
- pcdev->frame_interval = 0;
+ pcdev->last_fps = 0;
+ pcdev->frame_interval = 0;
hrtimer_cancel(&(pcdev->fps_timer.timer));
pcdev->fps_timer.pcdev = pcdev;
- pcdev->timer_get_fps = false;
- pcdev->reinit_times = 0;
- pcdev->stop_cif = false;
- pcdev->cif_stopped = false;
- // hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
+ pcdev->timer_get_fps = false;
+ pcdev->reinit_times = 0;
+
+ spin_lock_irqsave(&pcdev->lock,flags);
+ atomic_set(&pcdev->stop_cif,false);
+ pcdev->irqinfo.cifirq_idx = 0;
+ pcdev->irqinfo.cifirq_normal_idx = 0;
+ pcdev->irqinfo.cifirq_abnormal_idx = 0;
+ pcdev->irqinfo.dmairq_idx = 0;
+
+ write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); /*capture complete interrupt enable*/
cif_ctrl_val |= ENABLE_CAPTURE;
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+ spin_unlock_irqrestore(&pcdev->lock,flags);
+ printk("%s:stream enable CIF_CIF_CTRL 0x%lx\n",__func__,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
- pcdev->fps_timer.istarted = true;
+ pcdev->fps_timer.istarted = true;
} else {
- //cancel timer before stop cif
+ /*cancel timer before stop cif*/
ret = hrtimer_cancel(&pcdev->fps_timer.timer);
pcdev->fps_timer.istarted = false;
flush_work(&(pcdev->camera_reinit_work.work));
+
cif_ctrl_val &= ~ENABLE_CAPTURE;
spin_lock_irqsave(&pcdev->lock, flags);
- // write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
- pcdev->stop_cif = true;
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+ atomic_set(&pcdev->stop_cif,true);
+ write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x0);
spin_unlock_irqrestore(&pcdev->lock, flags);
-#if CONFIG_CIF_STOP_SYNC
- init_waitqueue_head(&pcdev->cif_stop_done);
- if (wait_event_timeout(pcdev->cif_stop_done, pcdev->cif_stopped, msecs_to_jiffies(1000)) == 0) {
- RKCAMERA_DG("%s:%d, wait cif stop timeout!",__func__,__LINE__);
- }
-#endif
- //mdelay(35);
flush_workqueue((pcdev->camera_wq));
- RK30_CAM_DEBUG_TRACE("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
+ msleep(100);
}
- //must be reinit,or will be somthing wrong in irq process.
+ /*must be reinit,or will be somthing wrong in irq process.*/
if(enable == false) {
+ //pcdev->active = NULL;
pcdev->active0 = NULL;
pcdev->active1 = NULL;
+ pcdev->active_buf = 0;
INIT_LIST_HEAD(&pcdev->capture);
- }
+ }
+ RKCAMERA_DG1("s_stream: enable : 0x%x , CIF_CIF_CTRL = 0x%lx\n",enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
return 0;
}
int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct rk_camera_frmivalenum *fival_list = NULL;
struct v4l2_frmivalenum *fival_head = NULL;
+ struct rkcamera_platform_data *new_camera;
int i,ret = 0,index;
+ const struct soc_camera_format_xlate *xlate;
+ struct v4l2_mbus_framefmt mf;
+ __u32 pixfmt;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
index = fival->index & 0x00ffffff;
if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
ret = -EINVAL;
}
} else {
- RK30_CAM_DEBUG_TRACE("%s: fival_list is NULL\n",__FUNCTION__);
+ RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
ret = -EINVAL;
}
} else {
- for (i=0; i<RK_CAM_NUM; i++) {
- if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
- fival_head = pcdev->pdata->info[i].fival;
- }
- }
-
- if (fival_head == NULL) {
- RK30_CAM_DEBUG_TRACE("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
- ret = -EINVAL;
- goto rk_camera_enum_frameintervals_end;
- }
-
- i = 0;
- while (fival_head->width && fival_head->height) {
- if ((fival->pixel_format == fival_head->pixel_format)
- && (fival->height == fival_head->height)
- && (fival->width == fival_head->width)) {
- if (i == index) {
- break;
+ if (fival_head) {
+ i = 0;
+ while (fival_head->width && fival_head->height) {
+ if ((fival->pixel_format == fival_head->pixel_format)
+ && (fival->height == fival_head->height)
+ && (fival->width == fival_head->width)) {
+ if (i == index) {
+ break;
+ }
+ i++;
}
- i++;
+ fival_head++;
}
- fival_head++;
- }
- if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
- memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
- RK30_CAM_DEBUG_TRACE("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
- fival->width, fival->height,
- fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
- (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
- fival->discrete.denominator,fival->discrete.numerator);
- } else {
- if (index == 0)
- RK30_CAM_DEBUG_TRACE("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
- fival->width,fival->height,
- fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
- (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
- index);
- else
- RK30_CAM_DEBUG_TRACE("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
- fival->width,fival->height,
+ if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
+ memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
+
+ pixfmt = fival->pixel_format; /* ddl@rock-chips.com: v0.3.9 */
+ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+ memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
+ mf.width = fival->width;
+ mf.height = fival->height;
+ mf.code = xlate->code;
+
+ v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+
+ fival->reserved[1] = (mf.width<<16)|(mf.height);
+
+ RKCAMERA_DG1("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
+ fival->width, fival->height,
fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
(fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
- index);
- ret = -EINVAL;
+ fival->discrete.denominator,fival->discrete.numerator);
+ } else {
+ if (index == 0)
+ RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
+ fival->width,fival->height,
+ fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
+ (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
+ index);
+ else
+ RKCAMERA_DG1("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
+ fival->width,fival->height,
+ fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
+ (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
+ index);
+ ret = -EINVAL;
+ goto rk_camera_enum_frameintervals_end;
+ }
+ } else {
+ i = 0x00;
+ new_camera = pcdev->pdata->register_dev_new;
+ while(new_camera != NULL){
+ if (strcmp(new_camera->dev_name, dev_name(pcdev->icd->pdev)) == 0) {
+ i = 0x01;
+ break;
+ }
+ new_camera = new_camera->next_camera;
+ }
+
+ if (i == 0x00) {
+ printk(KERN_ERR "%s(%d): %s have not found in new_camera[] and rk_camera_platform_data!",
+ __FUNCTION__,__LINE__,dev_name(pcdev->icd->pdev));
+ } else {
+
+ pixfmt = fival->pixel_format; /* ddl@rock-chips.com: v0.3.9 */
+ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+ memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
+ mf.width = fival->width;
+ mf.height = fival->height;
+ mf.code = xlate->code;
+
+ v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+
+ fival->discrete.numerator= 1000;
+ fival->discrete.denominator = 15000;
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->reserved[1] = (mf.width<<16)|(mf.height);
+ }
}
}
rk_camera_enum_frameintervals_end:
return ret;
}
-#ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
const struct v4l2_queryctrl *qctrl, int zoom_rate)
{
struct v4l2_crop a;
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
struct rk_camera_dev *pcdev = ici->priv;
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
#if CIF_DO_CROP
unsigned long tmp_cifctrl;
#endif
- //change the crop and scale parameters
+ /*change the crop and scale parameters*/
#if CIF_DO_CROP
- a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- //a.c.width = pcdev->host_width*100/zoom_rate;
- a.c.width = pcdev->host_width*100/zoom_rate;
- a.c.width &= ~CROP_ALIGN_BYTES;
- a.c.height = pcdev->host_height*100/zoom_rate;
- a.c.height &= ~CROP_ALIGN_BYTES;
- a.c.left = (((pcdev->host_width - a.c.width)>>1)+pcdev->host_left)&(~0x01);
- a.c.top = (((pcdev->host_height - a.c.height)>>1)+pcdev->host_top)&(~0x01);
- pcdev->stop_cif = true;
- tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
- hrtimer_cancel(&(pcdev->fps_timer.timer));
- flush_workqueue((pcdev->camera_wq));
- down(&pcdev->zoominfo.sem);
- pcdev->zoominfo.a.c.left = 0;
- pcdev->zoominfo.a.c.top = 0;
- pcdev->zoominfo.a.c.width = a.c.width;
- pcdev->zoominfo.a.c.height = a.c.height;
- pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
- pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
- pcdev->frame_inval = 1;
- write_cif_reg(pcdev->base,CIF_CIF_CROP, (a.c.left + (a.c.top<<16)));
- write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, ((a.c.width ) + (a.c.height<<16)));
- write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
- write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
+ a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /*a.c.width = pcdev->host_width*100/zoom_rate;*/
+ a.c.width = pcdev->host_width*100/zoom_rate;
+ a.c.width &= ~CROP_ALIGN_BYTES;
+ a.c.height = pcdev->host_height*100/zoom_rate;
+ a.c.height &= ~CROP_ALIGN_BYTES;
+ a.c.left = (((pcdev->host_width - a.c.width)>>1)+pcdev->host_left)&(~0x01);
+ a.c.top = (((pcdev->host_height - a.c.height)>>1)+pcdev->host_top)&(~0x01);
+ atomic_set(&pcdev->stop_cif,true);
+ tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
+ hrtimer_cancel(&(pcdev->fps_timer.timer));
+ flush_workqueue((pcdev->camera_wq));
+
+ down(&pcdev->zoominfo.sem);
+ pcdev->zoominfo.a.c.left = 0;
+ pcdev->zoominfo.a.c.top = 0;
+ pcdev->zoominfo.a.c.width = a.c.width;
+ pcdev->zoominfo.a.c.height = a.c.height;
+ pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
+ pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
+ pcdev->frame_inval = 1;
+ write_cif_reg(pcdev->base,CIF_CIF_CROP, (a.c.left + (a.c.top<<16)));
+ write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, ((a.c.width ) + (a.c.height<<16)));
+ write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
+ write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
+ //if(pcdev->active)
+ //rk_videobuf_capture(pcdev->active,pcdev);
if(pcdev->active0)
rk_videobuf_capture(pcdev->active0,pcdev,0);
if(pcdev->active1)
rk_videobuf_capture(pcdev->active1,pcdev,1);
- if(tmp_cifctrl & ENABLE_CAPTURE)
- write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
- up(&pcdev->zoominfo.sem);
- pcdev->stop_cif = false;
- hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
- RK30_CAM_DEBUG_TRACE("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
+ if(tmp_cifctrl & ENABLE_CAPTURE)
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
+ up(&pcdev->zoominfo.sem);
+
+ atomic_set(&pcdev->stop_cif,false);
+ hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
+ RKCAMERA_DG1("zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n", zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
#else
- a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- a.c.width = pcdev->host_width*100/zoom_rate;
- a.c.width &= ~CROP_ALIGN_BYTES;
- a.c.height = pcdev->host_height*100/zoom_rate;
- a.c.height &= ~CROP_ALIGN_BYTES;
- a.c.left = (pcdev->host_width - a.c.width)>>1;
- a.c.top = (pcdev->host_height - a.c.height)>>1;
- down(&pcdev->zoominfo.sem);
- pcdev->zoominfo.a.c.height = a.c.height;
- pcdev->zoominfo.a.c.width = a.c.width;
- pcdev->zoominfo.a.c.top = a.c.top;
- pcdev->zoominfo.a.c.left = a.c.left;
- pcdev->zoominfo.vir_width = pcdev->host_width;
- pcdev->zoominfo.vir_height= pcdev->host_height;
- up(&pcdev->zoominfo.sem);
- RK30_CAM_DEBUG_TRACE("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
+ a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ a.c.width = pcdev->host_width*100/zoom_rate;
+ a.c.width &= ~CROP_ALIGN_BYTES;
+ a.c.height = pcdev->host_height*100/zoom_rate;
+ a.c.height &= ~CROP_ALIGN_BYTES;
+ a.c.left = (pcdev->host_width - a.c.width)>>1;
+ a.c.top = (pcdev->host_height - a.c.height)>>1;
+
+ down(&pcdev->zoominfo.sem);
+ pcdev->zoominfo.a.c.height = a.c.height;
+ pcdev->zoominfo.a.c.width = a.c.width;
+ pcdev->zoominfo.a.c.top = a.c.top;
+ pcdev->zoominfo.a.c.left = a.c.left;
+ pcdev->zoominfo.vir_width = pcdev->host_width;
+ pcdev->zoominfo.vir_height= pcdev->host_height;
+ up(&pcdev->zoominfo.sem);
+
+ RKCAMERA_DG1("zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n", zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
#endif
return 0;
}
-#endif
+
static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
struct soc_camera_host_ops *ops, int id)
{
- int i;
+ int i;
for (i = 0; i < ops->num_controls; i++)
if (ops->controls[i].id == id)
return &ops->controls[i];
static int rk_camera_set_ctrl(struct soc_camera_device *icd,
struct v4l2_control *sctrl)
{
-
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);/*yzm*/
const struct v4l2_queryctrl *qctrl;
-#ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
struct rk_camera_dev *pcdev = ici->priv;
-#endif
+
int ret = 0;
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
if (!qctrl) {
ret = -ENOIOCTLCMD;
goto rk_camera_set_ctrl_end;
}
-
- if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
- ret = -EINVAL;
- goto rk_camera_set_ctrl_end;
- }
-
+
switch (sctrl->id)
{
- #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
case V4L2_CID_ZOOM_ABSOLUTE:
{
-
+ if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
+ ret = -EINVAL;
+ goto rk_camera_set_ctrl_end;
+ }
ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
if (ret == 0) {
pcdev->zoominfo.zoom_rate = sctrl->value;
}
break;
}
- #endif
-
- case V4L2_CID_HDR:
- {
- if (pcdev->hdr_info.en != sctrl->value) {
- pcdev->hdr_info.en = sctrl->value;
- if (sctrl->value) {
- struct device *control = to_soc_camera_control(pcdev->icd);
- struct v4l2_subdev *sd=dev_get_drvdata(control);
-
- printk("hdr on\n");
- pcdev->hdr_info.frame[0].code = RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1;
- pcdev->hdr_info.frame[0].set_ts = 0;
- pcdev->hdr_info.frame[0].get_ts = 0;
- pcdev->hdr_info.frame[1].code = RK_VIDEOBUF_HDR_EXPOSURE_NORMAL;
- pcdev->hdr_info.frame[1].set_ts = 0;
- pcdev->hdr_info.frame[1].get_ts = 0;
- pcdev->hdr_info.frame[2].code = RK_VIDEOBUF_HDR_EXPOSURE_PLUS_1;
- pcdev->hdr_info.frame[2].set_ts = 0;
- pcdev->hdr_info.frame[2].get_ts = 0;
- v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,RK_VIDEOBUF_HDR_EXPOSURE_NORMAL);
- }
- }
- break;
- }
-
default:
ret = -ENOIOCTLCMD;
break;
return ret;
}
-int rk_camera_enum_fsizes(struct soc_camera_device *icd, struct v4l2_frmsizeenum *fsize)
-{
- struct device *control = to_soc_camera_control(icd);
- struct v4l2_subdev *sd;
-
- sd = dev_get_drvdata(control);
- return v4l2_subdev_call(sd, video, enum_framesizes, fsize);
-
-}
-
static struct soc_camera_host_ops rk_soc_camera_host_ops =
{
.owner = THIS_MODULE,
.suspend = rk_camera_suspend,
.resume = rk_camera_resume,
.enum_frameinervals = rk_camera_enum_frameintervals,
- .enum_fsizes = rk_camera_enum_fsizes,
+ .cropcap = rk_camera_cropcap,
.set_crop = rk_camera_set_crop,
+ .get_crop = rk_camera_get_crop,
.get_formats = rk_camera_get_formats,
.put_formats = rk_camera_put_formats,
.set_fmt = rk_camera_set_fmt,
.num_controls = ARRAY_SIZE(rk_camera_controls)
};
-static void rk_camera_cif_iomux(int cif_index)
+/**********yzm***********/
+static int rk_camera_cif_iomux(struct device *dev)
{
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
- switch(cif_index){
- case 0:
- iomux_set(CIF0_CLKOUT);
- write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_4MA));
- write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));
- #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
- iomux_set(CIF0_D0);
- iomux_set(CIF0_D1);
- #endif
- #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
- iomux_set(CIF0_D10);
- iomux_set(CIF0_D11);
- RK30_CAM_DEBUG_TRACE("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
- #endif
-
- break;
- default:
- RK30_CAM_DEBUG_TRACE("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
- break;
+
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *state;
+ int retval = 0;
+ char state_str[20] = {0};
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+ strcpy(state_str,"cif_pin_jpe");
+
+ /*__raw_writel(((1<<1)|(1<<(1+16))),RK_GRF_VIRT+0x0380);*/
+
+
+ /*mux CIF0_CLKOUT*/
+
+ pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(pinctrl)) {
+ printk(KERN_EMERG "%s:Get pinctrl failed!\n",__func__);
+ return -1;
}
-#elif defined(CONFIG_ARCH_RK30)
- switch(cif_index){
- case 0:
- rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
- #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
- rk30_mux_api_set(GPIO1B4_CIF0DATA0_NAME, GPIO1B_CIF0_DATA0);
- rk30_mux_api_set(GPIO1B5_CIF0DATA1_NAME, GPIO1B_CIF0_DATA1);
- #endif
- #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
- rk30_mux_api_set(GPIO1B6_CIFDATA10_NAME, GPIO1B_CIF_DATA10);
- rk30_mux_api_set(GPIO1B7_CIFDATA11_NAME, GPIO1B_CIF_DATA11);
- #endif
- break;
- case 1:
- rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
- rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
- rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
- rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
- rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
- rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
- rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
- rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
-
- rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
- rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
- rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
- rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
- rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
- rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
- rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
- rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
- break;
- default:
- RK30_CAM_DEBUG_TRACE("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
- break;
+ state = pinctrl_lookup_state(pinctrl,
+ state_str);
+ if (IS_ERR(state)){
+ dev_err(dev, "%s:could not get %s pinstate\n",__func__,state_str);
+ return -1;
}
-#endif
-
+
+ if (!IS_ERR(state)) {
+ retval = pinctrl_select_state(pinctrl, state);
+ if (retval){
+ dev_err(dev,
+ "%s:could not set %s pins\n",__func__,state_str);
+ return -1;
+
+ }
+ }
+ return 0;
}
+/***********yzm***********/
static int rk_camera_probe(struct platform_device *pdev)
{
struct rk_camera_dev *pcdev;
struct resource *res;
struct rk_camera_frmivalenum *fival_list,*fival_nxt;
- struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
int irq,i;
int err = 0;
struct rk_cif_clk *clk=NULL;
+ struct device *dev_cif = ((struct rk29camera_platform_data*)pdev->dev.platform_data)->cif_dev;/*yzm*/
- printk("%s version: v%d.%d.%d Zoom by %s\n",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+ RKCAMERA_TR("%s version: v%d.%d.%d Zoom by %s",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
(RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);
if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
- RK30_CAM_DEBUG_TRACE("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
+ RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
BUG();
}
if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
- RK30_CAM_DEBUG_TRACE("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
+ RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
BUG();
}
-
+
+/***********yzm**********/
+ rk_camera_diffchips(((struct rk29camera_platform_data*)pdev->dev.platform_data)->rockchip_name);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
+
+ /* irq = irq_of_parse_and_map(dev_cif->of_node, 0);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n res = [%x--%x] \n",res->start , res->end);
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n irq_num = %d\n", irq);
+ */
if (!res || irq < 0) {
err = -ENODEV;
goto exit;
goto exit_alloc;
}
- pcdev->zoominfo.zoom_rate = 100;
- pcdev->hostid = pdev->id;
- /*config output clk*/ // must modify start
- if(IS_CIF0()){
+ pcdev->zoominfo.zoom_rate = 100;
+ pcdev->hostid = pdev->id; /* get host id*/
+ #ifdef CONFIG_SOC_RK3028
+ pcdev->chip_id = rk3028_version_val();
+ #else
+ pcdev->chip_id = -1;
+ #endif
+
+ /***********yzm***********/
+ if (IS_CIF0()) {
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$/is_cif0\n");
clk = &cif_clk[0];
- cif_clk[0].pd_cif = clk_get(NULL, "pd_cif0");
- cif_clk[0].aclk_cif = clk_get(NULL, "aclk_cif0");
- cif_clk[0].hclk_cif = clk_get(NULL, "hclk_cif0");
- cif_clk[0].cif_clk_in = clk_get(NULL, "cif0_in");
- cif_clk[0].cif_clk_out = clk_get(NULL, "cif0_out");
- spin_lock_init(&cif_clk[0].lock);
+ cif_clk[0].pd_cif = devm_clk_get(dev_cif, "pd_cif0");
+ cif_clk[0].aclk_cif = devm_clk_get(dev_cif, "aclk_cif0");
+ cif_clk[0].hclk_cif = devm_clk_get(dev_cif, "hclk_cif0");
+ cif_clk[0].cif_clk_in = devm_clk_get(dev_cif, "cif0_in");
+ cif_clk[0].cif_clk_out = devm_clk_get(dev_cif, "cif0_out");
+ //spin_lock_init(&cif_clk[0].lock);
cif_clk[0].on = false;
- rk_camera_cif_iomux(0);
+ rk_camera_cif_iomux(dev_cif);/*yzm*/
} else {
- clk = &cif_clk[1];
- cif_clk[1].pd_cif = clk_get(NULL, "pd_cif1");
- cif_clk[1].aclk_cif = clk_get(NULL, "aclk_cif1");
- cif_clk[1].hclk_cif = clk_get(NULL, "hclk_cif1");
- cif_clk[1].cif_clk_in = clk_get(NULL, "cif1_in");
- cif_clk[1].cif_clk_out = clk_get(NULL, "cif1_out");
- spin_lock_init(&cif_clk[1].lock);
+ clk = &cif_clk[1];
+ cif_clk[1].pd_cif = devm_clk_get(dev_cif, "pd_cif0");/*cif0 only yzm*/
+ cif_clk[1].aclk_cif = devm_clk_get(dev_cif, "aclk_cif0");
+ cif_clk[1].hclk_cif = devm_clk_get(dev_cif, "hclk_cif0");
+ cif_clk[1].cif_clk_in = devm_clk_get(dev_cif, "cif0_in");
+ cif_clk[1].cif_clk_out = devm_clk_get(dev_cif, "cif0_out");
+ //spin_lock_init(&cif_clk[1].lock);
cif_clk[1].on = false;
-
- rk_camera_cif_iomux(1);
+ rk_camera_cif_iomux(dev_cif);/*yzm*/
}
-
-
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
+ /***********yzm**********/
dev_set_drvdata(&pdev->dev, pcdev);
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
- pcdev->pdata->sensor_mclk = rk_camera_mclk_ctrl;
+ /*= rk_camera_platform_data */
if (pcdev->pdata && pcdev->pdata->io_init) {
- pcdev->pdata->io_init();
- }
- #ifdef CONFIG_VIDEO_RK29_WORK_IPP
- meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
- meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
-
- if (meminfo_ptr->vbase == NULL) {
-
- if ((meminfo_ptr->start == meminfo_ptrr->start)
- && (meminfo_ptr->size == meminfo_ptrr->size) && meminfo_ptrr->vbase) {
+
+ pcdev->pdata->io_init();/* call rk_sensor_io_init()*/
- meminfo_ptr->vbase = meminfo_ptrr->vbase;
- } else {
-
- if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) {
- err = -EBUSY;
- RK30_CAM_DEBUG_TRACE("%s(%d): request_mem_region(start:0x%x size:0x%x) failed \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
- goto exit_ioremap_vipmem;
- }
- meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size);
- if (pcdev->vipmem_virbase == NULL) {
- RK30_CAM_DEBUG_TRACE("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
- err = -ENXIO;
- goto exit_ioremap_vipmem;
- }
- }
+ if (pcdev->pdata->sensor_mclk == NULL)
+ pcdev->pdata->sensor_mclk = rk_camera_mclk_ctrl;
}
-
- pcdev->vipmem_phybase = meminfo_ptr->start;
- pcdev->vipmem_size = meminfo_ptr->size;
- pcdev->vipmem_virbase = meminfo_ptr->vbase;
- #endif
+
INIT_LIST_HEAD(&pcdev->capture);
INIT_LIST_HEAD(&pcdev->camera_work_queue);
spin_lock_init(&pcdev->lock);
}
}
- pcdev->irq = irq;
+ pcdev->irqinfo.irq = irq;
pcdev->dev = &pdev->dev;
/* config buffer address */
/* request irq */
if(irq > 0){
- err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
+ err = request_irq(pcdev->irqinfo.irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
pcdev);
if (err) {
dev_err(pcdev->dev, "Camera interrupt register failed \n");
}
}
-//#ifdef CONFIG_VIDEO_RK29_WORK_IPP
if(IS_CIF0()) {
pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
} else {
pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
}
- if (pcdev->camera_wq == NULL)
- goto exit_free_irq;
-//#endif
+ if (pcdev->camera_wq == NULL) {
+ RKCAMERA_TR("%s(%d): Create workqueue failed!\n",__FUNCTION__,__LINE__);
+ goto exit_free_irq;
+ }
pcdev->camera_reinit_work.pcdev = pcdev;
INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
}
pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
pcdev->soc_host.ops = &rk_soc_camera_host_ops;
- pcdev->soc_host.priv = pcdev;
+ pcdev->soc_host.priv = pcdev; /*to itself,csll in rk_camera_add_device*/
pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
pcdev->soc_host.nr = pdev->id;
-
+ debug_printk("/$$$$$$$$$$$$$$$$$$$$$$/next soc_camera_host_register\n");
err = soc_camera_host_register(&pcdev->soc_host);
- if (err)
+
+
+ if (err) {
+ RKCAMERA_TR("%s(%d): soc_camera_host_register failed\n",__FUNCTION__,__LINE__);
goto exit_free_irq;
+ }
pcdev->fps_timer.pcdev = pcdev;
hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pcdev->fps_timer.timer.function = rk_camera_fps_func;
pcdev->icd_cb.sensor_cb = NULL;
-#if ((defined(CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON)) && (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP))
+
+#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
#elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp;
#endif
- RK30_CAM_DEBUG_TRACE("%s(%d) Exit \n",__FUNCTION__,__LINE__);
return 0;
exit_free_irq:
}
}
- free_irq(pcdev->irq, pcdev);
+ free_irq(pcdev->irqinfo.irq, pcdev);
if (pcdev->camera_wq) {
destroy_workqueue(pcdev->camera_wq);
pcdev->camera_wq = NULL;
iounmap(pcdev->base);
exit_ioremap_vip:
release_mem_region(res->start, res->end - res->start + 1);
-exit_ioremap_vipmem:
- if (pcdev->vipmem_virbase)
- iounmap(pcdev->vipmem_virbase);
- release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size);
exit_reqmem_vip:
- if(pcdev->aclk_cif)
- pcdev->aclk_cif = NULL;
- if(pcdev->hclk_cif)
- pcdev->hclk_cif = NULL;
- if(pcdev->cif_clk_in)
- pcdev->cif_clk_in = NULL;
- if(pcdev->cif_clk_out)
- pcdev->cif_clk_out = NULL;
-
+ if (clk) {
+ if (clk->pd_cif)
+ clk_put(clk->pd_cif);
+ if (clk->aclk_cif)
+ clk_put(clk->aclk_cif);
+ if (clk->hclk_cif)
+ clk_put(clk->hclk_cif);
+ if (clk->cif_clk_in)
+ clk_put(clk->cif_clk_in);
+ if (clk->cif_clk_out)
+ clk_put(clk->cif_clk_out);
+ }
kfree(pcdev);
exit_alloc:
return err;
}
-static int __devexit rk_camera_remove(struct platform_device *pdev)
+static int __exit rk_camera_remove(struct platform_device *pdev)
{
struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
struct resource *res;
struct rk_camera_frmivalenum *fival_list,*fival_nxt;
- struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
int i;
-
- free_irq(pcdev->irq, pcdev);
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
+
+ free_irq(pcdev->irqinfo.irq, pcdev);
if (pcdev->camera_wq) {
destroy_workqueue(pcdev->camera_wq);
soc_camera_host_unregister(&pcdev->soc_host);
- meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
- meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
- if (meminfo_ptr->vbase) {
- if (meminfo_ptr->vbase == meminfo_ptrr->vbase) {
- meminfo_ptr->vbase = NULL;
- } else {
- iounmap((void __iomem*)pcdev->vipmem_virbase);
- release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
- meminfo_ptr->vbase = NULL;
- }
- }
-
res = pcdev->res;
iounmap((void __iomem*)pcdev->base);
release_mem_region(res->start, res->end - res->start + 1);
static struct platform_driver rk_camera_driver =
{
.driver = {
- .name = RK29_CAM_DRV_NAME,
+ .name = RK29_CAM_DRV_NAME, /*host */
},
.probe = rk_camera_probe,
- .remove = __devexit_p(rk_camera_remove),
+ .remove = (rk_camera_remove),
};
static int rk_camera_init_async(void *unused)
{
- platform_driver_register(&rk_camera_driver);
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+ platform_driver_register(&rk_camera_driver);
return 0;
}
-static int __devinit rk_camera_init(void)
+static int __init rk_camera_init(void)
{
- RK30_CAM_DEBUG_TRACE("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
+
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
+
kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
+
return 0;
}
static void __exit rk_camera_exit(void)
{
+ debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
+
platform_driver_unregister(&rk_camera_driver);
}
MODULE_DESCRIPTION("RKSoc Camera Host driver");
MODULE_AUTHOR("ddl <ddl@rock-chips>");
MODULE_LICENSE("GPL");
-#endif
config CAMSYS_DRV
tristate "camsys driver "
- default y
+ default n
menu "RockChip camera system driver"
depends on CAMSYS_DRV
+source "drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig"
+
config CAMSYS_MRV
tristate "camsys driver for marvin isp "
default y
---help---
endmenu
+
obj-$(CONFIG_CAMSYS_DRV) += camsys_drv.o
obj-$(CONFIG_CAMSYS_MRV) += camsys_marvin.o camsys_mipicsi_phy.o camsys_soc_priv.o
obj-$(CONFIG_CAMSYS_CIF) += camsys_cif.o
+obj-y += ext_flashled_drv/
#include "camsys_mipicsi_phy.h"
#include "camsys_gpio.h"
#include "camsys_soc_priv.h"
+#include "ext_flashled_drv/rk_ext_fshled_ctl.h"
unsigned int camsys_debug=1;
module_param(camsys_debug, int, S_IRUGO|S_IWUSR);
extdev->dev_cfg = devio->dev_cfg;
extdev->fl.fl.active = devio->fl.fl.active;
+ extdev->fl.ext_fsh_dev = NULL;
+ //should register external flash device ?
+ if(strlen(devio->fl.fl_drv_name) && (strcmp(devio->fl.fl_drv_name,"Internal") != 0)
+ && (strcmp(devio->fl.fl_drv_name,"NC") != 0)){
+ //register flash device
+ extdev->fl.ext_fsh_dev = camsys_register_ext_fsh_dev(&devio->fl);
+ if(extdev->fl.ext_fsh_dev == NULL){
+ camsys_err("register ext flash %s failed!",devio->fl.fl_drv_name);
+ err = -EINVAL;
+ goto fail;
+ }
+ }
regulator_info = &devio->avdd;
regulator = &extdev->avdd;
for (i=(CamSys_Vdd_Start_Tag+1); i<CamSys_Vdd_End_Tag; i++) {
gpio++;
}
+ if(extdev->fl.ext_fsh_dev != NULL){
+ camsys_deregister_ext_fsh_dev(extdev->fl.ext_fsh_dev);
+ }
//spin_lock(&camsys_dev->lock);
mutex_lock(&camsys_dev->extdevs.mut);
list_del_init(&extdev->list);
}
gpio++;
}
+
+ if(extdev->fl.ext_fsh_dev != NULL){
+ camsys_deregister_ext_fsh_dev(extdev->fl.ext_fsh_dev);
+ }
camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
list_del_init(&extdev->list);
list_del_init(&extdev->active);
}
case CamSys_Flash_Trigger:
{
- camsys_dev->flash_trigger_cb(camsys_dev, devctl->on);
+ camsys_dev->flash_trigger_cb(camsys_dev,devctl->rev[0], devctl->on);
break;
}
case CamSys_IOMMU:
}
}
}
+ }else if(devctl->ops == CamSys_Flash_Trigger){
+ err = camsys_ext_fsh_ctrl(extdev->fl.ext_fsh_dev,devctl->rev[0],devctl->on);
}
} else {
list_add_tail(&camsys_dev->list, &camsys_devs.devs);
spin_unlock(&camsys_devs.lock);
-
+ camsys_init_ext_fsh_module();
camsys_trace(1, "Probe %s device success ", dev_name(&pdev->dev));
return 0;
request_mem_fail:
list_del_init(&camsys_dev->list);
spin_unlock(&camsys_devs.lock);
+ camsys_deinit_ext_fsh_module();
+
kfree(camsys_dev);
camsys_dev=NULL;
} else {
group = 5;
} else if (strstr(io_name,"PIN6")) {
group = 6;
- }
+ } else if (strstr(io_name,"PIN7")) {
+ group = 7;
+ } else if (strstr(io_name,"PIN8")) {
+ group = 8;
+ }
return group;
}
1) enable or disable IOMMU just depending on CONFIG_ROCKCHIP_IOMMU.
*v0.0x17.0:
1) isp iommu status depend on vpu iommu status.
+*v0.0x18.0:
+ 1) add flashlight RT8547 driver
+ 2) support torch mode
+*v0.0x19.0:
+ 1) set CONFIG_CAMSYS_DRV disable as default,enable in defconfig file if needed.
*/
-#define CAMSYS_DRIVER_VERSION KERNEL_VERSION(0,0x17,0)
+#define CAMSYS_DRIVER_VERSION KERNEL_VERSION(0,0x19,0)
#define CAMSYS_PLATFORM_DRV_NAME "RockChip-CamSys"
} camsys_gpio_t;
typedef struct camsys_flash_s {
camsys_gpio_t fl;
+ camsys_gpio_t fl_en;
+ void* ext_fsh_dev;
+ //flash call back
} camsys_flash_t;
typedef struct camsys_extdev_s {
unsigned char dev_name[CAMSYS_NAME_LEN];
int (*phy_cb) (camsys_extdev_t *extdev, camsys_sysctrl_t *devctl, void* ptr);
int (*iomux)(camsys_extdev_t *extdev,void *ptr);
int (*platform_remove)(struct platform_device *pdev);
- int (*flash_trigger_cb)(void *ptr, unsigned int on);
+ int (*flash_trigger_cb)(void *ptr,int mode , unsigned int on);
int (*iommu_cb)(void *ptr,camsys_sysctrl_t *devctl);
} camsys_dev_t;
return -1;
}
-static int camsys_mrv_flash_trigger_cb(void *ptr,unsigned int on)
+static int camsys_mrv_flash_trigger_cb(void *ptr,int mode,unsigned int on)
{
camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
struct device *dev = &(camsys_dev->pdev->dev);
--- /dev/null
+config FLASHLIGHT
+ bool "Flashlight Support"
+ default n
+ help
+ This option enables the led sysfs class in /sys/class/flashlight.
+
+config LEDS_RT8547
+ bool "LED Support for RT8547"
+ select RT_FLASH_LED
+ default n
+ help
+ This option enabled support for RT8547 LED drivers
+
+config LEDS_RT8547_DBG
+ bool "LED RT8547 Debug Info"
+ depends on LEDS_RT8547
+ default n
+ help
+ This option enabled RT8547 LED drivers debug option
+
+config RT_FLASH_LED
+ bool "Richtek flash LED driver support"
+ depends on FLASHLIGHT
+ default n
+ help
+ Say Y here to enable Richtek's flash LED driver HAL architecture
--- /dev/null
+obj-$(CONFIG_FLASHLIGHT) += flashlight.o rk_ext_fshled_ctl.o
+obj-$(CONFIG_RT_FLASH_LED) += rtfled.o
+obj-$(CONFIG_LEDS_RT8547) += leds-rt8547.o
--- /dev/null
+/* drivers/leds/flashlight.c
+ * Flashlight Class Device Driver
+ *
+ * Copyright (C) 2013 Richtek Technology Corp.
+ * Author: Patrick Chang <patrick_chang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include "flashlight.h"
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+static const char const *flashlight_type_string[] = {
+ [FLASHLIGHT_TYPE_XENON] = "Xenon",
+ [FLASHLIGHT_TYPE_LED] = "LED",
+ [FLASHLIFHT_TYPE_BULB] = "Bulb",
+};
+
+static const char const *flashlight_mode_string[] = {
+ [FLASHLIGHT_MODE_OFF] = "Off",
+ [FLASHLIGHT_MODE_TORCH] = "Torch",
+ [FLASHLIGHT_MODE_FLASH] = "Flash",
+ [FLASHLIGHT_MODE_MIXED] = "Mixed",
+};
+
+static ssize_t flashlight_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%s\n",
+ flashlight_dev->props.alias_name ?
+ flashlight_dev->props.alias_name : "anonymous");
+}
+
+static ssize_t flashlight_show_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%s\n",
+ flashlight_type_string[flashlight_dev->props.type]);
+}
+
+static ssize_t flashlight_show_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%s\n",
+ flashlight_mode_string[flashlight_dev->props.mode]);
+}
+
+static ssize_t flashlight_show_torch_max_brightness(struct device *dev,
+ struct device_attribute
+ *attr, char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n", flashlight_dev->props.torch_max_brightness);
+}
+
+static ssize_t flashlight_show_strobe_max_brightness(struct device *dev,
+ struct device_attribute
+ *attr, char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n",
+ flashlight_dev->props.strobe_max_brightness);
+}
+
+static ssize_t flashlight_show_color_temperature(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n", flashlight_dev->props.color_temperature);
+}
+
+static ssize_t flashlight_show_strobe_delay(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n", flashlight_dev->props.strobe_delay);
+}
+
+static ssize_t flashlight_store_strobe_timeout(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc;
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+ long timeout;
+
+ rc = kstrtol(buf, 0, &timeout);
+ if (rc)
+ return rc;
+ rc = flashlight_dev->ops->set_strobe_timeout(flashlight_dev, timeout);
+ if (rc == 0)
+ rc = count;
+ return rc;
+}
+
+static ssize_t flashlight_show_strobe_timeout(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n", flashlight_dev->props.strobe_timeout);
+}
+
+static ssize_t flashlight_store_torch_brightness(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc;
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+ long brightness;
+
+ rc = kstrtol(buf, 0, &brightness);
+ if (rc)
+ return rc;
+
+ rc = -ENXIO;
+
+ mutex_lock(&flashlight_dev->ops_lock);
+ if (flashlight_dev->ops && flashlight_dev->ops->set_torch_brightness) {
+ if (brightness > flashlight_dev->props.torch_max_brightness)
+ rc = -EINVAL;
+ else {
+ pr_debug("flashlight: set torch brightness to %ld\n",
+ brightness);
+ flashlight_dev->props.torch_brightness = brightness;
+ flashlight_dev->ops->
+ set_torch_brightness(flashlight_dev, brightness);
+ rc = count;
+ }
+ }
+ mutex_unlock(&flashlight_dev->ops_lock);
+
+ return rc;
+}
+
+static ssize_t flashlight_show_torch_brightness(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n", flashlight_dev->props.torch_brightness);
+}
+
+static ssize_t flashlight_store_strobe_brightness(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc;
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+ long brightness;
+
+ rc = kstrtol(buf, 0, &brightness);
+ if (rc)
+ return rc;
+
+ rc = -ENXIO;
+
+ mutex_lock(&flashlight_dev->ops_lock);
+ if (flashlight_dev->ops && flashlight_dev->ops->set_strobe_brightness) {
+ if (brightness > flashlight_dev->props.strobe_max_brightness)
+ rc = -EINVAL;
+ else {
+ pr_debug("flashlight: set strobe brightness to %ld\n",
+ brightness);
+ flashlight_dev->props.strobe_brightness = brightness;
+ flashlight_dev->ops->
+ set_strobe_brightness(flashlight_dev, brightness);
+ rc = count;
+ }
+ }
+ mutex_unlock(&flashlight_dev->ops_lock);
+ return rc;
+}
+
+static ssize_t flashlight_show_strobe_brightness(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ return sprintf(buf, "%d\n", flashlight_dev->props.strobe_brightness);
+}
+
+static struct class *flashlight_class;
+
+static int flashlight_suspend(struct device *dev, pm_message_t state)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ if (flashlight_dev->ops)
+ flashlight_dev->ops->suspend(flashlight_dev, state);
+ return 0;
+}
+
+static int flashlight_resume(struct device *dev)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ if (flashlight_dev->ops)
+ flashlight_dev->ops->resume(flashlight_dev);
+ return 0;
+}
+
+static void flashlight_device_release(struct device *dev)
+{
+ struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+ kfree(flashlight_dev);
+}
+
+static struct device_attribute flashlight_device_attributes[] = {
+ __ATTR(name, 0444, flashlight_show_name, NULL),
+ __ATTR(type, 0444, flashlight_show_type, NULL),
+ __ATTR(mode, 0444, flashlight_show_mode, NULL),
+ __ATTR(torch_max_brightness, 0444,
+ flashlight_show_torch_max_brightness, NULL),
+ __ATTR(strobe_max_brightness, 0444,
+ flashlight_show_strobe_max_brightness, NULL),
+ __ATTR(color_temperature, 0444,
+ flashlight_show_color_temperature, NULL),
+ __ATTR(strobe_delay, 0444,
+ flashlight_show_strobe_delay, NULL),
+ __ATTR(strobe_timeout, 0644,
+ flashlight_show_strobe_timeout,
+ flashlight_store_strobe_timeout),
+ __ATTR(torch_brightness, 0644,
+ flashlight_show_torch_brightness,
+ flashlight_store_torch_brightness),
+ __ATTR(strobe_brightness, 0644,
+ flashlight_show_strobe_brightness,
+ flashlight_store_strobe_brightness),
+ __ATTR_NULL,
+};
+
+/**
+ * flashlight_device_register - create and register a new object of
+ * flashlight_device class.
+ * @name: the name of the new object(must be the same as the name of the
+ * respective framebuffer device).
+ * @parent: a pointer to the parent device
+ * @devdata: an optional pointer to be stored for private driver use. The
+ * methods may retrieve it by using bl_get_data(flashlight_dev).
+ * @ops: the flashlight operations structure.
+ *
+ * Creates and registers new flashlight device. Returns either an
+ * ERR_PTR() or a pointer to the newly allocated device.
+ */
+struct flashlight_device *flashlight_device_register(const char *name,
+ struct device *parent,
+ void *devdata,
+ const struct flashlight_ops
+ *ops,
+ const struct
+ flashlight_properties
+ *props)
+{
+ struct flashlight_device *flashlight_dev;
+ int rc;
+
+ pr_debug("flashlight_device_register: name=%s\n", name);
+ flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
+ if (!flashlight_dev)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_init(&flashlight_dev->ops_lock);
+ flashlight_dev->dev.class = flashlight_class;
+ flashlight_dev->dev.parent = parent;
+ flashlight_dev->dev.release = flashlight_device_release;
+ dev_set_name(&flashlight_dev->dev, name);
+ dev_set_drvdata(&flashlight_dev->dev, devdata);
+ /* Copy properties */
+ if (props) {
+ memcpy(&flashlight_dev->props, props,
+ sizeof(struct flashlight_properties));
+ }
+ rc = device_register(&flashlight_dev->dev);
+ if (rc) {
+ kfree(flashlight_dev);
+ return ERR_PTR(rc);
+ }
+ flashlight_dev->ops = ops;
+ return flashlight_dev;
+}
+EXPORT_SYMBOL(flashlight_device_register);
+
+/**
+ * flashlight_device_unregister - unregisters a flashlight device object.
+ * @flashlight_dev: the flashlight device object to be unregistered and freed.
+ *
+ * Unregisters a previously registered via flashlight_device_register object.
+ */
+void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
+{
+ if (!flashlight_dev)
+ return;
+
+ mutex_lock(&flashlight_dev->ops_lock);
+ flashlight_dev->ops = NULL;
+ mutex_unlock(&flashlight_dev->ops_lock);
+ device_unregister(&flashlight_dev->dev);
+}
+EXPORT_SYMBOL(flashlight_device_unregister);
+
+int flashlight_list_color_temperature(struct flashlight_device *flashlight_dev,
+ int selector)
+{
+ if (flashlight_dev->ops && flashlight_dev->ops->list_color_temperature)
+ return flashlight_dev->ops->
+ list_color_temperature(flashlight_dev, selector);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_list_color_temperature);
+
+int flashlight_set_color_temperature(struct flashlight_device *flashlight_dev,
+ int minK, int maxK)
+{
+ int selector = 0;
+ int rc;
+
+ if ((flashlight_dev->ops == NULL) ||
+ (flashlight_dev->ops->set_color_temperature == NULL))
+ return -EINVAL;
+ for (selector = 0;; selector++) {
+ rc = flashlight_list_color_temperature(flashlight_dev,
+ selector);
+ if (rc < 0)
+ return rc;
+ if (rc >= minK && rc <= maxK) {
+ mutex_lock(&flashlight_dev->ops_lock);
+ rc = flashlight_dev->ops->
+ set_color_temperature(flashlight_dev, rc);
+ mutex_unlock(&flashlight_dev->ops_lock);
+ if (rc == 0)
+ flashlight_dev->props.color_temperature = rc;
+ return rc;
+ }
+
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_set_color_temperature);
+
+int flashlight_set_torch_brightness(struct flashlight_device *flashlight_dev,
+ int brightness_level)
+{
+ int rc;
+
+ if ((flashlight_dev->ops == NULL) ||
+ (flashlight_dev->ops->set_torch_brightness == NULL))
+ return -EINVAL;
+ if (brightness_level > flashlight_dev->props.torch_max_brightness)
+ return -EINVAL;
+ mutex_lock(&flashlight_dev->ops_lock);
+ rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
+ brightness_level);
+ mutex_unlock(&flashlight_dev->ops_lock);
+ if (rc < 0)
+ return rc;
+ flashlight_dev->props.torch_brightness = brightness_level;
+ return rc;
+
+}
+EXPORT_SYMBOL(flashlight_set_torch_brightness);
+
+int flashlight_set_strobe_brightness(struct flashlight_device *flashlight_dev,
+ int brightness_level)
+{
+ int rc;
+
+ if ((flashlight_dev->ops == NULL) ||
+ (flashlight_dev->ops->set_strobe_brightness == NULL))
+ return -EINVAL;
+ if (brightness_level > flashlight_dev->props.strobe_max_brightness)
+ return -EINVAL;
+ mutex_lock(&flashlight_dev->ops_lock);
+ rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
+ brightness_level);
+ mutex_unlock(&flashlight_dev->ops_lock);
+ if (rc < 0)
+ return rc;
+ flashlight_dev->props.strobe_brightness = brightness_level;
+ return rc;
+}
+EXPORT_SYMBOL(flashlight_set_strobe_brightness);
+
+int flashlight_list_strobe_timeout(struct flashlight_device *flashlight_dev,
+ int selector)
+{
+ if (flashlight_dev->ops && flashlight_dev->ops->list_strobe_timeout) {
+ return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
+ selector);
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_list_strobe_timeout);
+
+int flashlight_set_strobe_timeout(struct flashlight_device *flashlight_dev,
+ int min_ms, int max_ms)
+{
+ int selector = 0;
+ int rc = -EINVAL;
+ int timeout;
+
+ if ((flashlight_dev->ops == NULL) ||
+ (flashlight_dev->ops->set_strobe_timeout == NULL))
+ return -EINVAL;
+ for (selector = 0;; selector++) {
+ timeout =
+ flashlight_list_strobe_timeout(flashlight_dev, selector);
+ if (timeout < 0)
+ return timeout;
+ if (timeout >= min_ms && timeout <= max_ms) {
+ mutex_lock(&flashlight_dev->ops_lock);
+ rc = flashlight_dev->ops->
+ set_strobe_timeout(flashlight_dev, timeout);
+ mutex_unlock(&flashlight_dev->ops_lock);
+ if (rc == 0)
+ flashlight_dev->props.strobe_timeout = timeout;
+ return rc;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_set_strobe_timeout);
+
+int flashlight_set_mode(struct flashlight_device *flashlight_dev, int mode)
+{
+ int rc;
+
+ if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
+ return -EINVAL;
+ if ((flashlight_dev->ops == NULL) ||
+ (flashlight_dev->ops->set_mode == NULL)) {
+ flashlight_dev->props.mode = mode;
+ return 0;
+ }
+ mutex_lock(&flashlight_dev->ops_lock);
+ rc = flashlight_dev->ops->set_mode(flashlight_dev, mode);
+ mutex_unlock(&flashlight_dev->ops_lock);
+ if (rc < 0)
+ return rc;
+ flashlight_dev->props.mode = mode;
+ return rc;
+}
+EXPORT_SYMBOL(flashlight_set_mode);
+
+int flashlight_strobe(struct flashlight_device *flashlight_dev)
+{
+ if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
+ || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
+ if (flashlight_dev->ops == NULL ||
+ flashlight_dev->ops->strobe == NULL)
+ return -EINVAL;
+ return flashlight_dev->ops->strobe(flashlight_dev);
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_strobe);
+
+static int flashlight_match_device_by_name(struct device *dev, const void *data)
+{
+ const char *name = data;
+
+ return strcmp(dev_name(dev), name) == 0;
+}
+
+struct flashlight_device *find_flashlight_by_name(char *name)
+{
+ struct device *dev;
+
+ if (!name)
+ return (struct flashlight_device *)NULL;
+ dev = class_find_device(flashlight_class, NULL, (void*)name,
+ flashlight_match_device_by_name);
+
+ return dev ? to_flashlight_device(dev) : NULL;
+
+}
+EXPORT_SYMBOL(find_flashlight_by_name);
+
+int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
+ flashlight_charge_event_cb cb, void *data,
+ int start)
+{
+
+ if (flashlight_dev->ops->strobe_charge)
+ return flashlight_dev->ops->strobe_charge(flashlight_dev,
+ cb, data, start);
+ if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
+ if (cb)
+ cb(data, 0);
+ return 0;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_strobe_charge);
+
+static void __exit flashlight_class_exit(void)
+{
+ class_destroy(flashlight_class);
+}
+
+static int __init flashlight_class_init(void)
+{
+ flashlight_class = class_create(THIS_MODULE, "flashlight");
+ if (IS_ERR(flashlight_class)) {
+ pr_err(
+ "Unable to create flashlight class; errno = %ld\n",
+ PTR_ERR(flashlight_class));
+ return PTR_ERR(flashlight_class);
+ }
+ flashlight_class->dev_attrs = flashlight_device_attributes;
+ flashlight_class->suspend = flashlight_suspend;
+ flashlight_class->resume = flashlight_resume;
+ return 0;
+}
+subsys_initcall(flashlight_class_init);
+module_exit(flashlight_class_exit);
+
+MODULE_DESCRIPTION("Flashlight Class Device");
+MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
+MODULE_VERSION("1.0.0_G");
+MODULE_LICENSE("GPL");
--- /dev/null
+/* include/linux/leds/flashlight.h
+ * Header of Flashlight Class Device Driver
+ *
+ * Copyright (C) 2013 Richtek Technology Corp.
+ * Patrick Chang <patrick_chang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef LINUX_LEDS_FLASHLIGHT_H
+#define LINUX_LEDS_FLASHLIGHT_H
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+typedef enum flashlight_type {
+ FLASHLIGHT_TYPE_XENON = 0,
+ FLASHLIGHT_TYPE_LED,
+ FLASHLIFHT_TYPE_BULB,
+ FLASHLIGHT_TYPE_MAX,
+} flashlight_type_t;
+typedef enum flashlight_mode {
+ FLASHLIGHT_MODE_OFF = 0,
+ FLASHLIGHT_MODE_TORCH,
+ FLASHLIGHT_MODE_FLASH,
+ /* MIXED mode means TORCH + FLASH */
+ FLASHLIGHT_MODE_MIXED,
+ FLASHLIGHT_MODE_MAX,
+} flashlight_mode_t;
+
+struct flashlight_device;
+
+typedef int (*flashlight_charge_event_cb) (void *data, int remains);
+
+struct flashlight_ops {
+ int (*set_torch_brightness)(struct flashlight_device *, int);
+ int (*set_strobe_brightness)(struct flashlight_device *, int);
+ int (*set_strobe_timeout)(struct flashlight_device *, int);
+ int (*list_strobe_timeout)(struct flashlight_device *, int);
+ int (*set_mode)(struct flashlight_device *, int);
+ int (*set_color_temperature)(struct flashlight_device *, int);
+ int (*list_color_temperature)(struct flashlight_device *, int);
+ int (*strobe_charge)(struct flashlight_device *,
+ flashlight_charge_event_cb, void *, int);
+ int (*strobe)(struct flashlight_device *);
+ int (*suspend)(struct flashlight_device *, pm_message_t);
+ int (*resume)(struct flashlight_device *);
+};
+
+struct flashlight_properties {
+ /* Flashlight type */
+ enum flashlight_type type;
+ /* Xenon type flashlight doesn't support torch mode */
+ enum flashlight_mode mode;
+ /* Color temperature, unit: K, 0 means unknown */
+ int color_temperature;
+ int torch_brightness;
+ int torch_max_brightness;
+ int strobe_brightness;
+ int strobe_max_brightness;
+ int strobe_delay;
+ int strobe_timeout;
+ const char *alias_name;
+};
+
+struct flashlight_device {
+ /* Flashlight properties */
+ struct flashlight_properties props;
+ const struct flashlight_ops *ops;
+ struct mutex ops_lock;
+ struct device dev;
+};
+
+extern struct flashlight_device *flashlight_device_register(const char *name,
+ struct device *parent,
+ void *devdata,
+ const struct
+ flashlight_ops * ops,
+ const struct
+ flashlight_properties
+ *props);
+extern void flashlight_device_unregister(struct flashlight_device
+ *flashlight_dev);
+extern struct flashlight_device *find_flashlight_by_name(char *name);
+extern int flashlight_list_color_temperature(struct flashlight_device
+ *flashlight_dev, int selector);
+extern int flashlight_set_color_temperature(struct flashlight_device
+ *flashlight_dev, int minK,
+ int maxK);
+extern int flashlight_set_torch_brightness(struct flashlight_device
+ *flashlight_dev,
+ int brightness_level);
+extern int flashlight_set_strobe_brightness(struct flashlight_device
+ *flashlight_dev,
+ int brightness_level);
+extern int flashlight_list_strobe_timeout(struct flashlight_device
+ *flashlight_dev, int selector);
+extern int flashlight_set_strobe_timeout(struct flashlight_device
+ *flashlight_dev, int min_ms,
+ int max_ms);
+extern int flashlight_set_mode(struct flashlight_device *flashlight_dev,
+ int mode);
+
+extern int flashlight_strobe(struct flashlight_device *flashlight_dev);
+
+/* flashlight_charge_event_cb(void *data, int remains)
+ * description :
+ * callback function of flashlight charging progress
+ * arguments :
+ * @data : data pass by flashlight_strobe_charge()
+ * @remains : remained time to full chargerd, unit : ms ; 0 means ready
+ * return : 0 means succeess, otherwise see definitions in errno.h
+ */
+
+/* flashlight_strobe_chargestruct flashlight_device *flashlight_dev,
+ * flashlight_charge_event_cb cb, void *data, int start)
+ * description :
+ * flashlight start / stop charging
+ * @flashlight_dev : flashlight devices
+ * @flashlight_charge_event_cb : callback function to report progress
+ * @data : bypass to callback function
+ * @start : 1 means start; 0 means stop
+ */
+extern int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
+ flashlight_charge_event_cb cb, void *data,
+ int start);
+
+#define to_flashlight_device(obj) \
+ container_of(obj, struct flashlight_device, dev)
+
+static inline void *flashlight_get_data(struct flashlight_device
+ *flashlight_dev)
+{
+ return dev_get_drvdata(&flashlight_dev->dev);
+}
+#endif /*LINUX_LEDS_FLASHLIGHT_H */
--- /dev/null
+/*
+ * drivers/leds/leds-rt8547.c
+ * Driver for Richtek RT8547 LED Flash IC
+ *
+ * Copyright (C) 2014 Richtek Technology Corp.
+ * cy_huang <cy_huang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif /* #ifdef CONFIG_OF */
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#endif /* #ifdef CONFIG_DEBUG_FS */
+
+#include "rtfled.h"
+#include "leds-rt8547.h"
+
+struct rt8547_chip {
+ rt_fled_info_t base;
+ struct device *dev;
+ struct rt8547_platform_data *pdata;
+ spinlock_t io_lock;
+ unsigned char suspend:1;
+ int in_use_mode;
+#ifdef CONFIG_DEBUG_FS
+ struct flashlight_device *fled_dev;
+ unsigned char reg_addr;
+ unsigned char reg_data;
+#endif /* #ifdef CONFIG_DEBUG_FS */
+};
+
+#ifdef CONFIG_DEBUG_FS
+struct rt_debug_st {
+ void *info;
+ int id;
+};
+
+enum {
+ RT8547_DBG_REG,
+ RT8547_DBG_DATA,
+ RT8547_DBG_REGS,
+ RT8547_DBG_FLED,
+ RT8547_DBG_MAX
+};
+
+static struct dentry *debugfs_rt_dent;
+static struct dentry *debugfs_file[RT8547_DBG_MAX];
+static struct rt_debug_st rtdbg_data[RT8547_DBG_MAX];
+#endif /* #ifdef CONFIG_DEBUG_FS */
+
+static unsigned char rt8547_reg_initval[] = {
+ 0x06, /* REG 0x01 */
+ 0x12, /* REG 0x02 */
+ 0x02, /* REG 0x03 */
+ 0x0F, /* REG 0x04 */
+};
+
+static inline int rt8547_send_bit(struct rt8547_platform_data *pdata,
+ unsigned char bit)
+{
+ if (bit) {
+ gpio_set_value(pdata->flset_gpio, (~(pdata->flset_active) & 0x1));
+ udelay(RT8547_SHORT_DELAY);
+ gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+ udelay(RT8547_LONG_DELAY);
+ } else {
+ gpio_set_value(pdata->flset_gpio, (~(pdata->flset_active) & 0x1));
+ udelay(RT8547_LONG_DELAY);
+ gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+ udelay(RT8547_SHORT_DELAY);
+ }
+ return 0;
+}
+
+static inline int rt8547_send_byte(struct rt8547_platform_data *pdata,
+ unsigned char byte)
+{
+ int i;
+
+ /*Send order is high bit to low bit */
+ for (i = 7; i >= 0; i--)
+ rt8547_send_bit(pdata, byte & (0x1 << i));
+ return 0;
+}
+
+static inline int rt8547_send_special_byte(struct rt8547_platform_data *pdata,
+ unsigned char byte)
+{
+ int i;
+
+ /*Only send three bit for register address */
+ for (i = 2; i >= 0; i--)
+ rt8547_send_bit(pdata, byte & (0x1 << i));
+ return 0;
+}
+
+static inline int rt8547_start_xfer(struct rt8547_platform_data *pdata)
+{
+ gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+ udelay(RT8547_START_DELAY);
+ return 0;
+}
+
+static inline int rt8547_stop_xfer(struct rt8547_platform_data *pdata)
+{
+ /*Redundant one bit as the stop condition */
+ rt8547_send_bit(pdata, 1);
+ return 0;
+}
+
+static int rt8547_send_data(struct rt8547_chip *chip, unsigned char reg,
+ unsigned char data)
+{
+ struct rt8547_platform_data *pdata = chip->pdata;
+ unsigned long flags;
+ unsigned char xfer_data[3]; /*0: adddr, 1: reg, 2: reg data*/
+
+ xfer_data[0] = RT8547_ONEWIRE_ADDR;
+ xfer_data[1] = reg;
+ xfer_data[2] = data;
+ RT_DBG("rt8547-> 0: 0x%02x, 1: 0x%02x, 2: 0x%02x\n", xfer_data[0],
+ xfer_data[1], xfer_data[2]);
+ spin_lock_irqsave(&chip->io_lock, flags);
+ rt8547_start_xfer(pdata);
+ rt8547_send_byte(pdata, xfer_data[0]);
+ rt8547_send_special_byte(pdata, xfer_data[1]);
+ rt8547_send_byte(pdata, xfer_data[2]);
+ rt8547_stop_xfer(pdata);
+ spin_unlock_irqrestore(&chip->io_lock, flags);
+ /*write back to reg array*/
+ rt8547_reg_initval[reg - 1] = data;
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int reg_debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static int get_parameters(char *buf, long int *param1, int num_of_par)
+{
+ char *token;
+ int base, cnt;
+
+ token = strsep(&buf, " ");
+
+ for (cnt = 0; cnt < num_of_par; cnt++) {
+ if (token != NULL) {
+ if ((token[1] == 'x') || (token[1] == 'X'))
+ base = 16;
+ else
+ base = 10;
+
+ if (kstrtoul(token, base, ¶m1[cnt]) != 0)
+ return -EINVAL;
+
+ token = strsep(&buf, " ");
+ } else
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct rt_debug_st *st = filp->private_data;
+ struct rt8547_chip *di = st->info;
+ char lbuf[1000];
+ int i = 0, j = 0;
+
+ lbuf[0] = '\0';
+ switch (st->id) {
+ case RT8547_DBG_REG:
+ snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_addr);
+ break;
+ case RT8547_DBG_DATA:
+ di->reg_data = rt8547_reg_initval[di->reg_addr - 1];
+ snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_data);
+ break;
+ case RT8547_DBG_REGS:
+ for (i = RT8547_FLED_REG0; i < RT8547_FLED_REGMAX; i++)
+ j += snprintf(lbuf + j, 20, "0x%02x:%02x\n", i,
+ rt8547_reg_initval[i - 1]);
+ break;
+ case RT8547_DBG_FLED:
+ snprintf(lbuf, sizeof(lbuf), "%d\n", di->in_use_mode);
+ break;
+ default:
+ return -EINVAL;
+
+ }
+ return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
+}
+
+static ssize_t reg_debug_write(struct file *filp,
+ const char __user *ubuf, size_t cnt,
+ loff_t *ppos)
+{
+ struct rt_debug_st *st = filp->private_data;
+ struct rt8547_chip *di = st->info;
+ char lbuf[32];
+ int rc;
+ long int param[5];
+
+ if (cnt > sizeof(lbuf) - 1)
+ return -EINVAL;
+
+ rc = copy_from_user(lbuf, ubuf, cnt);
+ if (rc)
+ return -EFAULT;
+
+ lbuf[cnt] = '\0';
+
+ switch (st->id) {
+ case RT8547_DBG_REG:
+ rc = get_parameters(lbuf, param, 1);
+ if ((param[0] < RT8547_FLED_REGMAX) && (rc == 0)) {
+ if ((param[0] >= RT8547_FLED_REG0
+ && param[0] <= RT8547_FLED_REG3))
+ di->reg_addr = (unsigned char)param[0];
+ else
+ rc = -EINVAL;
+ } else
+ rc = -EINVAL;
+ break;
+ case RT8547_DBG_DATA:
+ rc = get_parameters(lbuf, param, 1);
+ if ((param[0] <= 0xff) && (rc == 0)) {
+ rt8547_send_data(di, di->reg_addr,
+ (unsigned char)param[0]);
+ } else
+ rc = -EINVAL;
+ break;
+ case RT8547_DBG_FLED:
+ if (!di->fled_dev)
+ di->fled_dev = find_flashlight_by_name("rt-flash-led");
+ rc = get_parameters(lbuf, param, 1);
+ if ((param[0] <= FLASHLIGHT_MODE_FLASH) && (rc == 0)
+ && di->fled_dev) {
+ switch (param[0]) {
+ case FLASHLIGHT_MODE_TORCH:
+ flashlight_set_torch_brightness(di->fled_dev,
+ 2);
+ flashlight_set_mode(di->fled_dev,
+ FLASHLIGHT_MODE_TORCH);
+ break;
+ case FLASHLIGHT_MODE_FLASH:
+ flashlight_set_strobe_timeout(di->fled_dev,
+ 256, 256);
+ flashlight_set_strobe_brightness(di->fled_dev,
+ 18);
+ flashlight_set_mode(di->fled_dev,
+ FLASHLIGHT_MODE_FLASH);
+ flashlight_strobe(di->fled_dev);
+ break;
+ case FLASHLIGHT_MODE_OFF:
+ flashlight_set_mode(di->fled_dev,
+ FLASHLIGHT_MODE_OFF);
+ break;
+ }
+ } else
+ rc = -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (rc == 0)
+ rc = cnt;
+ return rc;
+}
+
+static const struct file_operations reg_debug_ops = {
+ .open = reg_debug_open,
+ .write = reg_debug_write,
+ .read = reg_debug_read
+};
+
+static void rt8547_create_debugfs(struct rt8547_chip *chip)
+{
+ RT_DBG("add debugfs for RT8547\n");
+ debugfs_rt_dent = debugfs_create_dir("rt8547_dbg", 0);
+ if (!IS_ERR(debugfs_rt_dent)) {
+ rtdbg_data[0].info = chip;
+ rtdbg_data[0].id = RT8547_DBG_REG;
+ debugfs_file[0] = debugfs_create_file("reg",
+ S_IFREG | S_IRUGO,
+ debugfs_rt_dent,
+ (void *)&rtdbg_data[0],
+ ®_debug_ops);
+
+ rtdbg_data[1].info = chip;
+ rtdbg_data[1].id = RT8547_DBG_DATA;
+ debugfs_file[1] = debugfs_create_file("data",
+ S_IFREG | S_IRUGO,
+ debugfs_rt_dent,
+ (void *)&rtdbg_data[1],
+ ®_debug_ops);
+
+ rtdbg_data[2].info = chip;
+ rtdbg_data[2].id = RT8547_DBG_REGS;
+ debugfs_file[2] = debugfs_create_file("regs",
+ S_IFREG | S_IRUGO,
+ debugfs_rt_dent,
+ (void *)&rtdbg_data[2],
+ ®_debug_ops);
+
+ rtdbg_data[3].info = chip;
+ rtdbg_data[3].id = RT8547_DBG_FLED;
+ debugfs_file[3] = debugfs_create_file("fled",
+ S_IFREG | S_IRUGO,
+ debugfs_rt_dent,
+ (void *)&rtdbg_data[3],
+ ®_debug_ops);
+ } else {
+ dev_err(chip->dev, "create debugfs failed\n");
+ }
+}
+
+static void rt8547_remove_debugfs(void)
+{
+ if (!IS_ERR(debugfs_rt_dent))
+ debugfs_remove_recursive(debugfs_rt_dent);
+}
+#endif /* #ifdef CONFIG_DEBUG_FS */
+
+static inline void rt8547_fled_power_on(struct rt8547_platform_data *pdata)
+{
+ if (gpio_is_valid(pdata->flset_gpio))
+ gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+}
+
+static inline void rt8547_fled_power_off(struct rt8547_platform_data *pdata)
+{
+ if (gpio_is_valid(pdata->flset_gpio))
+ gpio_set_value(pdata->flset_gpio, (~(pdata->flset_active) & 0x1));
+ udelay(RT8547_STOP_DELAY);
+}
+
+static inline void rt8547_fled_ctrl_en(struct rt8547_platform_data *pdata,
+ int en)
+{
+ if (gpio_is_valid(pdata->ctl_gpio)){
+ if (en)
+ gpio_set_value(pdata->ctl_gpio, ((pdata->ctl_active) & 0x1));
+ else
+ gpio_set_value(pdata->ctl_gpio, (~(pdata->ctl_active) & 0x1));
+ }
+ RT_DBG("en %d\n", en);
+}
+
+static inline void rt8547_fled_flash_en(struct rt8547_platform_data *pdata,
+ int en)
+{
+ if (gpio_is_valid(pdata->flen_gpio)){
+ if (en)
+ gpio_set_value(pdata->flen_gpio, ((pdata->flen_active) & 0x1));
+ else
+ gpio_set_value(pdata->flen_gpio, (~(pdata->flen_active) & 0x1));
+ }
+ RT_DBG("en %d\n", en);
+}
+
+static int rt8547_fled_init(struct rt_fled_info *info)
+{
+ RT_DBG("\n");
+ return 0;
+}
+
+static int rt8547_fled_resume(struct rt_fled_info *info)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+ RT_DBG("\n");
+ fi->suspend = 0;
+ return 0;
+}
+
+static int rt8547_fled_suspend(struct rt_fled_info *info, pm_message_t state)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+ RT_DBG("\n");
+ fi->suspend = 1;
+ return 0;
+}
+
+static int rt8547_fled_set_mode(struct rt_fled_info *info,
+ flashlight_mode_t mode)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+ unsigned char tmp = 0;
+ int ret = 0;
+
+ RT_DBG("mode=%d\n", mode);
+ switch (mode) {
+ case FLASHLIGHT_MODE_TORCH:
+ if (fi->in_use_mode == FLASHLIGHT_MODE_OFF)
+ rt8547_fled_power_on(fi->pdata);
+ tmp = rt8547_reg_initval[RT8547_FLED_REG2 - 1];
+ tmp |= RT8547_MODESEL_MASK;
+ rt8547_send_data(fi, RT8547_FLED_REG2, tmp);
+ rt8547_fled_ctrl_en(fi->pdata, 1);
+ rt8547_fled_flash_en(fi->pdata, 1);
+ fi->in_use_mode = mode;
+ break;
+ case FLASHLIGHT_MODE_FLASH:
+ if (fi->in_use_mode == FLASHLIGHT_MODE_OFF)
+ rt8547_fled_power_on(fi->pdata);
+ tmp = rt8547_reg_initval[RT8547_FLED_REG2 - 1];
+ tmp &= ~RT8547_MODESEL_MASK;
+ rt8547_send_data(fi, RT8547_FLED_REG2, tmp);
+ fi->in_use_mode = mode;
+ break;
+ case FLASHLIGHT_MODE_OFF:
+ rt8547_fled_flash_en(fi->pdata, 0);
+ rt8547_fled_ctrl_en(fi->pdata, 0);
+ if (fi->in_use_mode != FLASHLIGHT_MODE_OFF)
+ rt8547_fled_power_off(fi->pdata);
+ fi->in_use_mode = mode;
+ break;
+ case FLASHLIGHT_MODE_MIXED:
+ default:
+ ret = -EINVAL;
+ }
+ return 0;
+}
+
+static int rt8547_fled_get_mode(struct rt_fled_info *info)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+ RT_DBG("\n");
+ return fi->in_use_mode;
+}
+
+static int rt8547_fled_strobe(struct rt_fled_info *info)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+ RT_DBG("\n");
+ rt8547_fled_flash_en(fi->pdata, 0);
+ rt8547_fled_ctrl_en(fi->pdata, 0);
+ rt8547_fled_ctrl_en(fi->pdata, 1);
+ rt8547_fled_flash_en(fi->pdata, 1);
+ return 0;
+}
+
+static int rt8547_fled_torch_current_list(struct rt_fled_info *info,
+ int selector)
+{
+ RT_DBG("selector=%d\n", selector);
+ return 25000 + selector * 25000; /* unit: uA */
+}
+
+static int rt8547_fled_strobe_current_list(struct rt_fled_info *info,
+ int selector)
+{
+ RT_DBG("selector=%d\n", selector);
+ return 100000 + selector * 50000; /* unit: uA */
+}
+
+static int rt8547_fled_timeout_level_list(struct rt_fled_info *info,
+ int selector)
+{
+ RT_DBG("selector=%d\n", selector);
+ return 100000 + selector * 50000; /* unit: uA */
+}
+
+static int rt8547_fled_lv_protection_list(struct rt_fled_info *info,
+ int selector)
+{
+ RT_DBG("selector=%d\n", selector);
+ return 3000 + selector * 100; /* unit: mV */
+}
+
+static int rt8547_fled_strobe_timeout_list(struct rt_fled_info *info,
+ int selector)
+{
+ RT_DBG("selector=%d\n", selector);
+ return 64 + selector * 32; /* unit: mS */
+}
+
+static int rt8547_fled_set_torch_current_sel(struct rt_fled_info *info,
+ int selector)
+{
+
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+ unsigned char tmp = 0;
+
+ RT_DBG("selector=%d\n", selector);
+ tmp = rt8547_reg_initval[RT8547_FLED_REG2 - 1];
+ tmp &= ~RT8547_TCLEVEL_MASK;
+ tmp |= selector;
+ rt8547_send_data(fi, RT8547_FLED_REG2, tmp);
+ return 0;
+}
+
+static int rt8547_fled_set_strobe_current_sel(struct rt_fled_info *info,
+ int selector)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+ unsigned char tmp = 0;
+
+ RT_DBG("selector=%d\n", selector);
+ tmp = rt8547_reg_initval[RT8547_FLED_REG1 - 1];
+ tmp &= ~RT8547_SCLEVEL_MASK;
+ tmp |= selector;
+ rt8547_send_data(fi, RT8547_FLED_REG1, tmp);
+ return 0;
+}
+
+static int rt8547_fled_set_timeout_level_sel(struct rt_fled_info *info,
+ int selector)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+ unsigned char tmp = 0;
+
+ RT_DBG("selector=%d\n", selector);
+ if (selector > RT8547_TOL_MAX)
+ return -EINVAL;
+ tmp = rt8547_reg_initval[RT8547_FLED_REG1 - 1];
+ tmp &= ~RT8547_TOCLEVEL_MASK;
+ tmp |= (selector << RT8547_TOCLEVEL_SHFT);
+ rt8547_send_data(fi, RT8547_FLED_REG1, tmp);
+ return 0;
+}
+
+static int rt8547_fled_set_lv_protection_sel(struct rt_fled_info *info,
+ int selector)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+ unsigned char tmp = 0;
+
+ RT_DBG("selector=%d\n", selector);
+ if (selector > RT8547_LVP_MAX)
+ return -EINVAL;
+ tmp = rt8547_reg_initval[RT8547_FLED_REG0 - 1];
+ tmp &= ~RT8547_LVP_MASK;
+ tmp |= selector;
+ rt8547_send_data(fi, RT8547_FLED_REG0, tmp);
+ return 0;
+}
+
+static int rt8547_fled_set_strobe_timeout_sel(struct rt_fled_info *info,
+ int selector)
+{
+ struct rt8547_chip *fi = (struct rt8547_chip *)info;
+ unsigned char tmp = 0;
+
+ RT_DBG("selector=%d\n", selector);
+ if (selector > RT8547_STO_MAX)
+ return -EINVAL;
+ tmp = rt8547_reg_initval[RT8547_FLED_REG3 - 1];
+ tmp &= ~RT8547_STO_MASK;
+ tmp |= selector;
+ rt8547_send_data(fi, RT8547_FLED_REG3, tmp);
+ return 0;
+}
+
+static int rt8547_fled_get_torch_current_sel(struct rt_fled_info *info)
+{
+ int selector =
+ rt8547_reg_initval[RT8547_FLED_REG2 - 1] & RT8547_TCLEVEL_MASK;
+
+ return selector;
+}
+
+static int rt8547_fled_get_strobe_current_sel(struct rt_fled_info *info)
+{
+ int selector =
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1] & RT8547_SCLEVEL_MASK;
+
+ return selector;
+}
+
+static int rt8547_fled_get_timeout_level_sel(struct rt_fled_info *info)
+{
+ int selector =
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1] & RT8547_TOCLEVEL_MASK;
+
+ selector >>= RT8547_TOCLEVEL_SHFT;
+ return selector;
+}
+
+static int rt8547_fled_get_lv_protection_sel(struct rt_fled_info *info)
+{
+ int selector =
+ rt8547_reg_initval[RT8547_FLED_REG0 - 1] & RT8547_LVP_MASK;
+
+ return selector;
+}
+
+static int rt8547_fled_get_strobe_timeout_sel(struct rt_fled_info *info)
+{
+ int selector =
+ rt8547_reg_initval[RT8547_FLED_REG3 - 1] & RT8547_STO_MASK;
+
+ return selector;
+}
+
+static struct rt_fled_hal rt8547_fled_hal = {
+ .fled_init = rt8547_fled_init,
+ .fled_suspend = rt8547_fled_suspend,
+ .fled_resume = rt8547_fled_resume,
+ .fled_set_mode = rt8547_fled_set_mode,
+ .fled_get_mode = rt8547_fled_get_mode,
+ .fled_strobe = rt8547_fled_strobe,
+ .fled_torch_current_list = rt8547_fled_torch_current_list,
+ .fled_strobe_current_list = rt8547_fled_strobe_current_list,
+ .fled_timeout_level_list = rt8547_fled_timeout_level_list,
+ .fled_lv_protection_list = rt8547_fled_lv_protection_list,
+ .fled_strobe_timeout_list = rt8547_fled_strobe_timeout_list,
+ /* method to set */
+ .fled_set_torch_current_sel = rt8547_fled_set_torch_current_sel,
+ .fled_set_strobe_current_sel = rt8547_fled_set_strobe_current_sel,
+ .fled_set_timeout_level_sel = rt8547_fled_set_timeout_level_sel,
+ .fled_set_lv_protection_sel = rt8547_fled_set_lv_protection_sel,
+ .fled_set_strobe_timeout_sel = rt8547_fled_set_strobe_timeout_sel,
+ /* method to get */
+ .fled_get_torch_current_sel = rt8547_fled_get_torch_current_sel,
+ .fled_get_strobe_current_sel = rt8547_fled_get_strobe_current_sel,
+ .fled_get_timeout_level_sel = rt8547_fled_get_timeout_level_sel,
+ .fled_get_lv_protection_sel = rt8547_fled_get_lv_protection_sel,
+ .fled_get_strobe_timeout_sel = rt8547_fled_get_strobe_timeout_sel,
+};
+
+static struct flashlight_properties rt8547_fled_props = {
+ .type = FLASHLIGHT_TYPE_LED,
+ .torch_brightness = 2,
+ .torch_max_brightness = 15,
+ .strobe_brightness = 18,
+ .strobe_max_brightness = 30,
+ .strobe_delay = 2,
+ .strobe_timeout = 544,
+ .alias_name = "rt8547-fled",
+};
+
+static void rt8547_parse_dt(struct rt8547_platform_data *pdata,
+ struct device *dev)
+{
+#ifdef CONFIG_OF
+ struct device_node *np = dev->of_node;
+ u32 tmp;
+
+ if (of_property_read_u32(np, "rt,def_lvp", &tmp) < 0) {
+ dev_warn(dev, "use 3V as the default lvp\n");
+ } else {
+ if (tmp > RT8547_LVP_MAX)
+ tmp = RT8547_LVP_MAX;
+ rt8547_reg_initval[RT8547_FLED_REG0 - 1] &= ~RT8547_LVP_MASK;
+ rt8547_reg_initval[RT8547_FLED_REG0 - 1] |= tmp;
+ }
+
+ if (of_property_read_u32(np, "rt,def_tol", &tmp) < 0) {
+ dev_warn(dev, "use 100mA as the default timeout level\n");
+ } else {
+ if (tmp > RT8547_TOL_MAX)
+ tmp = RT8547_TOL_MAX;
+ tmp <<= RT8547_TOCLEVEL_SHFT;
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1] &=
+ ~RT8547_TOCLEVEL_MASK;
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1] |= tmp;
+ }
+ pdata->flen_gpio = of_get_named_gpio(np, "rt,flen_gpio", 0);
+ pdata->ctl_gpio = of_get_named_gpio(np, "rt,ctl_gpio", 0);
+ pdata->flset_gpio = of_get_named_gpio(np, "rt,flset_gpio", 0);
+#endif /* #ifdef CONFIG_OF */
+}
+
+static void rt8547_parse_pdata(struct rt8547_platform_data *pdata,
+ struct device *dev)
+{
+ u32 tmp;
+
+ tmp = pdata->def_lvp;
+ rt8547_reg_initval[RT8547_FLED_REG0 - 1] &= ~RT8547_LVP_MASK;
+ rt8547_reg_initval[RT8547_FLED_REG0 - 1] |= tmp;
+
+ tmp = pdata->def_tol;
+ tmp <<= RT8547_TOCLEVEL_SHFT;
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1] &= ~RT8547_TOCLEVEL_MASK;
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1] |= tmp;
+}
+
+static int rt8547_io_init(struct rt8547_platform_data *pdata,
+ struct device *dev)
+{
+ int rc = 0;
+
+ if (gpio_is_valid(pdata->flen_gpio)) {
+ rc = gpio_request_one(pdata->flen_gpio, ((~(pdata->flen_active) & 0x1) ? GPIOF_OUT_INIT_HIGH:GPIOF_OUT_INIT_LOW),
+ "rt8547_flen");
+ if (rc < 0) {
+ dev_err(dev, "request rt8547 flash en pin fail\n");
+ goto gpio_request1;
+ }
+
+ }
+
+ if(gpio_is_valid(pdata->ctl_gpio)){
+ rc = gpio_request_one(pdata->ctl_gpio, ((~(pdata->ctl_active) & 0x1) ? GPIOF_OUT_INIT_HIGH:GPIOF_OUT_INIT_LOW),
+ "rt8547_ctl");
+ if (rc < 0) {
+ dev_err(dev, "request rt8547 ctl pin fail\n");
+ goto gpio_request2;
+ }
+ }
+
+ if(gpio_is_valid(pdata->flset_gpio)){
+ rc = gpio_request_one(pdata->flset_gpio, ((~(pdata->flset_active) & 0x1) ? GPIOF_OUT_INIT_HIGH:GPIOF_OUT_INIT_LOW),
+ "rt8547_flset");
+ if (rc < 0) {
+ dev_err(dev, "request rt8547 flash set pin fail\n");
+ goto gpio_request3;
+ }
+ }
+ return 0;
+gpio_request3:
+ if(gpio_is_valid(pdata->ctl_gpio))
+ gpio_free(pdata->ctl_gpio);
+gpio_request2:
+ if (gpio_is_valid(pdata->flen_gpio))
+ gpio_free(pdata->flen_gpio);
+gpio_request1:
+ return rc;
+
+}
+
+static int rt8547_io_deinit(struct rt8547_platform_data *pdata)
+{
+ if (gpio_is_valid(pdata->flen_gpio)){
+ gpio_direction_input(pdata->flen_gpio);
+ gpio_free(pdata->flen_gpio);
+ }
+ if(gpio_is_valid(pdata->ctl_gpio)){
+ gpio_direction_input(pdata->ctl_gpio);
+ gpio_free(pdata->ctl_gpio);
+ }
+ if(gpio_is_valid(pdata->flset_gpio)){
+ gpio_direction_input(pdata->flset_gpio);
+ gpio_free(pdata->flset_gpio);
+ }
+ return 0;
+}
+
+static void rt8547_reg_init(struct rt8547_chip *chip)
+{
+ RT_DBG("\n");
+ rt8547_send_data(chip, RT8547_FLED_REG0,
+ rt8547_reg_initval[RT8547_FLED_REG0 - 1]);
+ rt8547_send_data(chip, RT8547_FLED_REG1,
+ rt8547_reg_initval[RT8547_FLED_REG1 - 1]);
+ rt8547_send_data(chip, RT8547_FLED_REG2,
+ rt8547_reg_initval[RT8547_FLED_REG2 - 1]);
+ rt8547_send_data(chip, RT8547_FLED_REG3,
+ rt8547_reg_initval[RT8547_FLED_REG3 - 1]);
+}
+
+static struct platform_device rt_fled_pdev = {
+ .name = "rt-flash-led",
+ .id = -1,
+};
+
+static int rt8547_led_probe(struct platform_device *pdev)
+{
+ struct rt8547_platform_data *pdata = pdev->dev.platform_data;
+ struct rt8547_chip *chip;
+ bool use_dt = pdev->dev.of_node;
+ int ret = 0;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+ if (use_dt) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ goto err_probe;
+ rt8547_parse_dt(pdata, &pdev->dev);
+ } else {
+ if (!pdata)
+ goto err_probe;
+ rt8547_parse_pdata(pdata, &pdev->dev);
+ }
+
+ ret = rt8547_io_init(pdata, &pdev->dev);
+ if (ret < 0)
+ goto err_io;
+
+ chip->dev = &pdev->dev;
+ chip->pdata = pdata;
+ spin_lock_init(&chip->io_lock);
+ chip->in_use_mode = FLASHLIGHT_MODE_OFF;
+ platform_set_drvdata(pdev, chip);
+
+ rt8547_fled_power_on(pdata);
+ rt8547_reg_init(chip);
+ rt8547_fled_power_off(pdata);
+
+ chip->base.hal = &rt8547_fled_hal;
+ chip->base.init_props = &rt8547_fled_props;
+ rt_fled_pdev.dev.parent = &pdev->dev;
+ ret = platform_device_register(&rt_fled_pdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "register rtfled fail\n");
+ goto err_io;
+ }
+#ifdef CONFIG_DEBUG_FS
+ rt8547_create_debugfs(chip);
+#endif /* #ifdef CONFIG_DEBUG_FS */
+ dev_info(&pdev->dev, "driver successfully registered\n");
+ return 0;
+err_io:
+ if (use_dt)
+ devm_kfree(&pdev->dev, pdata);
+err_probe:
+ devm_kfree(&pdev->dev, chip);
+ return ret;
+}
+
+static int rt8547_led_remove(struct platform_device *pdev)
+{
+ struct rt8547_chip *chip = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_DEBUG_FS
+ rt8547_remove_debugfs();
+#endif /* #ifdef CONFIG_DEBUG_FS */
+ platform_device_unregister(&rt_fled_pdev);
+ rt8547_io_deinit(chip->pdata);
+ return 0;
+}
+
+static const struct of_device_id rt_match_table[] = {
+ {.compatible = "rt,rt8547",},
+ {},
+};
+
+static struct platform_driver rt8547_led_driver = {
+ .driver = {
+ .name = "rt8547",
+ .owner = THIS_MODULE,
+ .of_match_table = rt_match_table,
+ },
+ .probe = rt8547_led_probe,
+ .remove = rt8547_led_remove,
+};
+
+static int rt8547_led_init(void)
+{
+ return platform_driver_register(&rt8547_led_driver);
+}
+
+module_init(rt8547_led_init);
+
+static void rt8547_led_exit(void)
+{
+ platform_driver_unregister(&rt8547_led_driver);
+}
+
+module_exit(rt8547_led_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("LED Flash Driver for RT8547");
+MODULE_VERSION(RT8547_DRV_VER);
--- /dev/null
+/* include/linux/leds-rt8547.h
+ * Include file of driver to Richtek RT8547 LED Flash IC
+ *
+ * Copyright (C) 2014 Richtek Technology Corporation
+ * Author: CY_Huang <cy_huang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_LEDS_RT8547_H
+#define __LINUX_LEDS_RT8547_H
+
+#define RT8547_DRV_VER "1.0.2_G"
+
+enum {
+ RT8547_FLED_REG0 = 0x01,
+ RT8547_FLED_REG1,
+ RT8547_FLED_REG2,
+ RT8547_FLED_REG3,
+ RT8547_FLED_REGMAX,
+};
+
+enum {
+ RT8547_LVP_3V,
+ RT8547_LVP_3P1V,
+ RT8547_LVP_3P2V,
+ RT8547_LVP_3P3V,
+ RT8547_LVP_3P4V,
+ RT8547_LVP_3P5V,
+ RT8547_LVP_3P6V,
+ RT8547_LVP_3P7V,
+ RT8547_LVP_3P8V,
+ RT8547_LVP_MAX = RT8547_LVP_3P8V,
+};
+
+enum {
+ RT8547_TOL_100mA,
+ RT8547_TOL_150mA,
+ RT8547_TOL_200mA,
+ RT8547_TOL_250mA,
+ RT8547_TOL_300mA,
+ RT8547_TOL_350mA,
+ RT8547_TOL_400mA,
+ RT8547_TOL_MAX = RT8547_TOL_400mA,
+};
+
+#define RT8547_STO_MAX 36
+
+#define RT8547_LVP_MASK 0x0F
+#define RT8547_TOCLEVEL_MASK 0xE0
+#define RT8547_TOCLEVEL_SHFT 5
+#define RT8547_SCLEVEL_MASK 0x1F
+#define RT8547_SWRST_MASK 0x20
+#define RT8547_MODESEL_MASK 0x10
+#define RT8547_TCLEVEL_MASK 0x0F
+#define RT8547_STO_MASK 0x3F
+
+struct rt8547_platform_data {
+ int flen_gpio;
+ int flen_active;
+ int ctl_gpio;
+ int ctl_active;
+ int flset_gpio;
+ int flset_active;
+ unsigned char def_lvp:4;
+ unsigned char def_tol:3;
+};
+
+/* one wire protocol parameter */
+#define RT8547_ONEWIRE_ADDR 0x99
+#define RT8547_LONG_DELAY 9
+#define RT8547_SHORT_DELAY 4
+#define RT8547_START_DELAY 10
+#define RT8547_STOP_DELAY 1500
+
+#ifdef CONFIG_LEDS_RT8547_DBG
+#define RT_DBG(fmt, args...) pr_info("%s: " fmt, __func__, ##args)
+#else
+#define RT_DBG(fmt, args...)
+#endif /* #ifdef CONFIG_LEDS_RT8547_DBG */
+
+#endif /* #ifndef __LINUX_LEDS_RT8547_H */
--- /dev/null
+#include "rk_ext_fshled_ctl.h"
+#include "../camsys_gpio.h"
+#include "flashlight.h"
+#include "leds-rt8547.h"
+
+typedef struct ext_fsh_info_s{
+ struct platform_device pdev;
+ char* dev_model;
+ struct list_head list;
+}ext_fsh_info_t;
+
+struct ext_fsh_dev_list_s{
+ struct list_head dev_list;
+};
+
+static struct ext_fsh_dev_list_s g_ext_fsh_devs;
+
+int camsys_init_ext_fsh_module()
+{
+ camsys_trace(1,"init external flash module");
+ INIT_LIST_HEAD(&g_ext_fsh_devs.dev_list);
+ return 0;
+}
+
+int camsys_deinit_ext_fsh_module()
+{
+ ext_fsh_info_t* cur_fsh_info = NULL;
+ camsys_trace(1,"deinit external flash module");
+ if (!list_empty(&g_ext_fsh_devs.dev_list)) {
+ list_for_each_entry(cur_fsh_info, &g_ext_fsh_devs.dev_list, list) {
+ if (cur_fsh_info) {
+ platform_device_unregister(&cur_fsh_info->pdev);
+ list_del_init(&cur_fsh_info->list);
+ /* free after unregister device ?*/
+ kfree(cur_fsh_info->pdev.dev.platform_data);
+ kfree(cur_fsh_info);
+ cur_fsh_info = NULL;
+ }
+ }
+ }
+
+ INIT_LIST_HEAD(&g_ext_fsh_devs.dev_list);
+ return 0;
+}
+void* camsys_register_ext_fsh_dev(camsys_flash_info_t *fsh_info)
+{
+ ext_fsh_info_t* new_dev = NULL;
+ if(strcmp(fsh_info->fl_drv_name,"rt8547") == 0){
+ struct rt8547_platform_data* new_rt_dev = NULL;
+ new_dev = kzalloc(sizeof(ext_fsh_info_t),GFP_KERNEL);
+ if(!new_dev){
+ camsys_err("register new ext flash dev erro !");
+ goto fail0;
+ }
+
+ new_rt_dev = kzalloc(sizeof(ext_fsh_info_t),GFP_KERNEL);
+ if(!new_rt_dev){
+ camsys_err("register new ext flash dev erro !");
+ goto fail1;
+ }
+
+ new_dev->pdev.id = -1;
+ new_dev->pdev.name = fsh_info->fl_drv_name;
+ new_dev->pdev.dev.platform_data = (void*)new_rt_dev;
+ new_dev->dev_model = "rt-flash-led";
+
+ new_rt_dev->flen_gpio = camsys_gpio_get(fsh_info->fl_en.name);
+ new_rt_dev->flen_active = fsh_info->fl_en.active;
+ camsys_trace(1,"flen name :%s,gpio %d,active %d \n",fsh_info->fl_en.name,new_rt_dev->flen_gpio,new_rt_dev->flen_active);
+ new_rt_dev->flset_gpio = camsys_gpio_get(fsh_info->fl.name );
+ new_rt_dev->flset_active = fsh_info->fl.active;
+ camsys_trace(1,"flset name :%s, gpio %d, active %d \n",fsh_info->fl.name,new_rt_dev->flset_gpio,new_rt_dev->flset_active);
+ new_rt_dev->ctl_gpio = -1;
+ new_rt_dev->def_lvp = RT8547_LVP_3V;
+ new_rt_dev->def_tol = RT8547_TOL_100mA;
+
+ // new_rt_dev->def_lvp = RT8547_LVP_MAX;
+ // new_rt_dev->def_tol = RT8547_TOL_MAX;
+
+ if(platform_device_register(&new_dev->pdev) < 0){
+ camsys_err("register rtfled fail\n");
+ kfree(new_rt_dev);
+ goto fail1;
+ }
+
+ list_add_tail(&new_dev->list, &g_ext_fsh_devs.dev_list);
+ camsys_trace(1,"register new rt led dev success !");
+ }
+
+ return (void*)new_dev;
+fail1:
+ if(new_dev)
+ kfree(new_dev);
+fail0:
+ return NULL;
+}
+
+int camsys_deregister_ext_fsh_dev(void* dev)
+{
+ ext_fsh_info_t* cur_fsh_info = NULL;
+ if (!list_empty(&g_ext_fsh_devs.dev_list)) {
+ list_for_each_entry(cur_fsh_info, &g_ext_fsh_devs.dev_list, list) {
+ if (dev == cur_fsh_info) {
+ camsys_trace(1,"unregister ext flsh dev !");
+ platform_device_unregister(&cur_fsh_info->pdev);
+ list_del_init(&cur_fsh_info->list);
+ /* free after unregister device ?*/
+ kfree(cur_fsh_info->pdev.dev.platform_data);
+ kfree(cur_fsh_info);
+ }
+ }
+ }
+ return 0;
+}
+
+/*******************************
+mode:
+ 0: CAM_ENGINE_FLASH_OFF = 0x00,
+ 1: CAM_ENGINE_FLASH_AUTO = 0x01,
+ 2: CAM_ENGINE_FLASH_ON = 0x02,
+ 3: CAM_ENGINE_FLASH_RED_EYE = 0x03,
+ 5: CAM_ENGINE_FLASH_TORCH = 0x05
+********************************/
+int camsys_ext_fsh_ctrl(void* dev,int mode,unsigned int on)
+{
+ ext_fsh_info_t* cur_fsh_info = NULL;
+ struct flashlight_device *fled_dev = NULL;
+ if (!list_empty(&g_ext_fsh_devs.dev_list)) {
+ list_for_each_entry(cur_fsh_info, &g_ext_fsh_devs.dev_list, list) {
+ if (dev == cur_fsh_info) {
+ break;
+ }
+ }
+ }
+ if(cur_fsh_info == NULL){
+ camsys_err("this flash dev have not been registered !");
+ return -1;
+ }
+
+ fled_dev = find_flashlight_by_name(cur_fsh_info->dev_model);
+ switch(mode){
+ case 0: /* off */
+ /* set flashlight mode to Off */
+ flashlight_set_mode(fled_dev, FLASHLIGHT_MODE_OFF);
+ break;
+ case 2: /* flash on */
+ /* set strobe timeout to 256ms */
+ //flashlight_set_strobe_timeout(fled_dev, 256, 256);
+ flashlight_set_strobe_timeout(fled_dev, 512, 512);
+ /* set strobe brightness to to index 18 (1A), refer to the datasheet for the others */
+ flashlight_set_strobe_brightness(fled_dev, 18);
+ /* set flashlight mode to Strobe */
+ flashlight_set_mode(fled_dev, FLASHLIGHT_MODE_FLASH);
+ flashlight_strobe(fled_dev);
+ break;
+ case 5: /* torch */
+ /* set the torch brightness index 2 (75mA), refer to the datasheet for index current value. */
+ flashlight_set_torch_brightness(fled_dev, 2);
+ /* set flashlight mode to Torch */
+ flashlight_set_mode(fled_dev, FLASHLIGHT_MODE_TORCH);
+ break;
+ default:
+ camsys_err("not support this mode %d !",mode);
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef __RK_EXT_FSHLED_H__
+#define __RK_EXT_FSHLED_H__
+#include "../camsys_internal.h"
+//register flash dev
+extern int camsys_init_ext_fsh_module(void);
+extern int camsys_deinit_ext_fsh_module(void);
+extern void* camsys_register_ext_fsh_dev(camsys_flash_info_t *fsh_info);
+extern int camsys_deregister_ext_fsh_dev(void* dev);
+extern int camsys_ext_fsh_ctrl(void* dev,int mode,unsigned int on);
+#endif
--- /dev/null
+/* drivers/leds/rtfled.c
+ * Richtek Flash LED Universal Architecture
+ *
+ * Copyright (C) 2013 Richtek Technology Corp.
+ * Author: Patrick Chang <patrick_chang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include "rtfled.h"
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define RTFLED_INFO(format, args...) \
+ pr_info("%s:%s() line-%d: " format, \
+ ALIAS_NAME, __func__, __LINE__, ## args)
+#define RTFLED_WARN(format, args...) \
+ pr_warn("%s:%s() line-%d: " format, \
+ ALIAS_NAME, __func__, __LINE__, ## args)
+#define RTFLED_ERR(format, args...) \
+ pr_err("%s:%s() line-%d: " format, \
+ ALIAS_NAME, __func__, __LINE__, ## args)
+
+#define RT_FLED_DEVICE "rt-flash-led"
+#define ALIAS_NAME RT_FLED_DEVICE
+
+rt_fled_info_t *rt_fled_get_info_by_name(char *name)
+{
+ struct flashlight_device *flashlight_dev;
+
+ flashlight_dev = find_flashlight_by_name(name ? name : RT_FLED_DEVICE);
+ if (flashlight_dev == NULL)
+ return (rt_fled_info_t *) NULL;
+ return flashlight_get_data(flashlight_dev);
+}
+EXPORT_SYMBOL(rt_fled_get_info_by_name);
+
+static int rtfled_set_torch_brightness(struct flashlight_device *flashlight_dev,
+ int brightness_sel)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ return info->hal->fled_set_torch_current_sel(info, brightness_sel);
+}
+
+static int rtfled_set_strobe_brightness(struct flashlight_device
+ *flashlight_dev, int brightness_sel)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ return info->hal->fled_set_strobe_current_sel(info, brightness_sel);
+}
+
+static int rtfled_set_strobe_timeout(struct flashlight_device *flashlight_dev,
+ int timeout)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ int sel;
+
+ return info->hal->fled_set_strobe_timeout(info, timeout, timeout, &sel);
+}
+
+static int rtfled_list_strobe_timeout(struct flashlight_device *flashlight_dev,
+ int selector)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ return info->hal->fled_strobe_timeout_list(info, selector);
+}
+
+static int rtfled_set_mode(struct flashlight_device *flashlight_dev, int mode)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ return info->hal->fled_set_mode(info, mode);
+}
+
+static int rtfled_strobe(struct flashlight_device *flashlight_dev)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ return info->hal->fled_strobe(info);
+}
+
+static int rtfled_set_color_temperature(struct flashlight_device
+ *flashlight_dev, int color_temp)
+{
+ /* Doesn't support color temperature */
+ return -EINVAL;
+}
+
+static int rtfled_list_color_temperature(struct flashlight_device
+ *flashlight_dev, int selector)
+{
+ /* Doesn't support color temperature */
+ return -EINVAL;
+}
+
+static int rtfled_suspend(struct flashlight_device *flashlight_dev,
+ pm_message_t state)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ if (info->hal->fled_suspend)
+ return info->hal->fled_suspend(info, state);
+ return 0;
+}
+
+static int rtfled_resume(struct flashlight_device *flashlight_dev)
+{
+ rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+ if (info->hal->fled_resume)
+ return info->hal->fled_resume(info);
+ return 0;
+}
+
+static struct flashlight_ops rtfled_impl_ops = {
+ .set_torch_brightness = rtfled_set_torch_brightness,
+ .set_strobe_brightness = rtfled_set_strobe_brightness,
+ .set_strobe_timeout = rtfled_set_strobe_timeout,
+ .list_strobe_timeout = rtfled_list_strobe_timeout,
+ .set_mode = rtfled_set_mode,
+ .strobe = rtfled_strobe,
+ .set_color_temperature = rtfled_set_color_temperature,
+ .list_color_temperature = rtfled_list_color_temperature,
+ .suspend = rtfled_suspend,
+ .resume = rtfled_resume,
+};
+
+static void rfled_shutdown(struct platform_device *pdev)
+{
+ struct rt_fled_info *info = platform_get_drvdata(pdev);
+
+ if (info->hal->fled_shutdown)
+ info->hal->fled_shutdown(info);
+}
+
+static int rtled_impl_set_torch_current(struct rt_fled_info *info,
+ int min_uA, int max_uA, int *selector)
+{
+ int sel = 0;
+ int rc;
+
+ for (sel = 0;; sel++) {
+ rc = info->hal->fled_torch_current_list(info, sel);
+ if (rc < 0)
+ return rc;
+ if (rc >= min_uA && rc <= max_uA) {
+ *selector = sel;
+ return info->hal->fled_set_torch_current_sel(info, sel);
+ }
+ }
+ return -EINVAL;
+}
+
+static int rtled_impl_set_strobe_current(struct rt_fled_info *info,
+ int min_uA, int max_uA, int *selector)
+{
+ int sel = 0;
+ int rc;
+
+ for (sel = 0;; sel++) {
+ rc = info->hal->fled_strobe_current_list(info, sel);
+ if (rc < 0)
+ return rc;
+ if (rc >= min_uA && rc <= max_uA) {
+ *selector = sel;
+ return info->hal->fled_set_strobe_current_sel(info,
+ sel);
+ }
+ }
+ return -EINVAL;
+}
+
+static int rtled_impl_set_timeout_level(struct rt_fled_info *info,
+ int min_uA, int max_uA, int *selector)
+{
+ int sel = 0;
+ int rc;
+
+ for (sel = 0;; sel++) {
+ rc = info->hal->fled_timeout_level_list(info, sel);
+ if (rc < 0)
+ return rc;
+ if (rc >= min_uA && rc <= max_uA) {
+ *selector = sel;
+ return info->hal->fled_set_timeout_level_sel(info, sel);
+ }
+ }
+ return -EINVAL;
+}
+
+static int rtled_impl_set_lv_protection(struct rt_fled_info *info,
+ int min_mV, int max_mV, int *selector)
+{
+ int sel = 0;
+ int rc;
+
+ for (sel = 0;; sel++) {
+ rc = info->hal->fled_lv_protection_list(info, sel);
+ if (rc < 0)
+ return rc;
+ if (rc >= min_mV && rc <= max_mV) {
+ *selector = sel;
+ return info->hal->fled_set_lv_protection_sel(info, sel);
+ }
+ }
+ return -EINVAL;
+}
+
+static int rtled_impl_set_strobe_timeout(struct rt_fled_info *info,
+ int min_ms, int max_ms, int *selector)
+{
+ int sel = 0;
+ int rc;
+
+ for (sel = 0;; sel++) {
+ rc = info->hal->fled_strobe_timeout_list(info, sel);
+ if (rc < 0)
+ return rc;
+ if (rc >= min_ms && rc <= max_ms) {
+ *selector = sel;
+ return info->hal->fled_set_strobe_timeout_sel(info,
+ sel);
+ }
+ }
+ return -EINVAL;
+}
+
+static int rtled_impl_get_torch_current(struct rt_fled_info *info)
+{
+ int sel = info->hal->fled_get_torch_current_sel(info);
+
+ if (sel < 0)
+ return sel;
+ return info->hal->fled_torch_current_list(info, sel);
+}
+
+static int rtled_impl_get_strobe_current(struct rt_fled_info *info)
+{
+ int sel = info->hal->fled_get_strobe_current_sel(info);
+
+ if (sel < 0)
+ return sel;
+ return info->hal->fled_strobe_current_list(info, sel);
+}
+
+static int rtled_impl_get_timeout_level(struct rt_fled_info *info)
+{
+ int sel = info->hal->fled_get_timeout_level_sel(info);
+
+ if (sel < 0)
+ return sel;
+ return info->hal->fled_timeout_level_list(info, sel);
+}
+
+static int rtled_impl_get_lv_protection(struct rt_fled_info *info)
+{
+ int sel = info->hal->fled_get_lv_protection_sel(info);
+
+ if (sel < 0)
+ return sel;
+ return info->hal->fled_lv_protection_list(info, sel);
+}
+
+static int rtled_impl_get_strobe_timeout(struct rt_fled_info *info)
+{
+ int sel = info->hal->fled_get_strobe_timeout_sel(info);
+
+ if (sel < 0)
+ return sel;
+ return info->hal->fled_strobe_timeout_list(info, sel);
+}
+
+#define HAL_NOT_IMPLEMENTED(x) (hal->x == NULL)
+#define CHECK_HAL_IMPLEMENTED(x) \
+ do { \
+ if (hal->x == NULL) \
+ return -EINVAL; \
+ } while (0)
+
+static int rtfled_check_hal_implement(struct rt_fled_hal *hal)
+{
+ if (HAL_NOT_IMPLEMENTED(fled_set_torch_current))
+ hal->fled_set_torch_current = rtled_impl_set_torch_current;
+ if (HAL_NOT_IMPLEMENTED(fled_set_strobe_current))
+ hal->fled_set_strobe_current = rtled_impl_set_strobe_current;
+ if (HAL_NOT_IMPLEMENTED(fled_set_timeout_level))
+ hal->fled_set_timeout_level = rtled_impl_set_timeout_level;
+ if (HAL_NOT_IMPLEMENTED(fled_set_lv_protection))
+ hal->fled_set_lv_protection = rtled_impl_set_lv_protection;
+ if (HAL_NOT_IMPLEMENTED(fled_set_strobe_timeout))
+ hal->fled_set_strobe_timeout = rtled_impl_set_strobe_timeout;
+ if (HAL_NOT_IMPLEMENTED(fled_get_torch_current))
+ hal->fled_get_torch_current = rtled_impl_get_torch_current;
+ if (HAL_NOT_IMPLEMENTED(fled_get_strobe_current))
+ hal->fled_get_strobe_current = rtled_impl_get_strobe_current;
+ if (HAL_NOT_IMPLEMENTED(fled_get_timeout_level))
+ hal->fled_get_timeout_level = rtled_impl_get_timeout_level;
+ if (HAL_NOT_IMPLEMENTED(fled_get_lv_protection))
+ hal->fled_get_lv_protection = rtled_impl_get_lv_protection;
+ if (HAL_NOT_IMPLEMENTED(fled_get_strobe_timeout))
+ hal->fled_get_strobe_timeout = rtled_impl_get_strobe_timeout;
+ CHECK_HAL_IMPLEMENTED(fled_set_mode);
+ CHECK_HAL_IMPLEMENTED(fled_get_mode);
+ CHECK_HAL_IMPLEMENTED(fled_strobe);
+ CHECK_HAL_IMPLEMENTED(fled_torch_current_list);
+ CHECK_HAL_IMPLEMENTED(fled_strobe_current_list);
+ CHECK_HAL_IMPLEMENTED(fled_timeout_level_list);
+ CHECK_HAL_IMPLEMENTED(fled_lv_protection_list);
+ CHECK_HAL_IMPLEMENTED(fled_strobe_timeout_list);
+ CHECK_HAL_IMPLEMENTED(fled_set_torch_current_sel);
+ CHECK_HAL_IMPLEMENTED(fled_set_strobe_current_sel);
+ CHECK_HAL_IMPLEMENTED(fled_set_timeout_level_sel);
+ CHECK_HAL_IMPLEMENTED(fled_set_lv_protection_sel);
+ CHECK_HAL_IMPLEMENTED(fled_set_strobe_timeout_sel);
+ CHECK_HAL_IMPLEMENTED(fled_get_torch_current_sel);
+ CHECK_HAL_IMPLEMENTED(fled_get_strobe_current_sel);
+ CHECK_HAL_IMPLEMENTED(fled_get_timeout_level_sel);
+ CHECK_HAL_IMPLEMENTED(fled_get_lv_protection_sel);
+ CHECK_HAL_IMPLEMENTED(fled_get_strobe_timeout_sel);
+ return 0;
+}
+
+static int rtfled_probe(struct platform_device *pdev)
+{
+ rt_fled_info_t *info = dev_get_drvdata(pdev->dev.parent);
+ int rc;
+
+ BUG_ON(info == NULL);
+ BUG_ON(info->hal == NULL);
+
+ RTFLED_INFO("Richtek FlashLED Driver is probing\n");
+ rc = rtfled_check_hal_implement(info->hal);
+ if (rc < 0) {
+ RTFLED_ERR("HAL implemented uncompletedly\n");
+ goto err_check_hal;
+ }
+ platform_set_drvdata(pdev, info);
+ info->flashlight_dev =
+ flashlight_device_register(info->name ? info->name : RT_FLED_DEVICE,
+ &pdev->dev, info, &rtfled_impl_ops,
+ info->init_props);
+ if (info->hal->fled_init) {
+ rc = info->hal->fled_init(info);
+ if (rc < 0) {
+ RTFLED_ERR("Initialization failed\n");
+ goto err_init;
+ }
+ }
+ RTFLED_INFO("Richtek FlashLED Driver initialized successfully\n");
+ return 0;
+err_init:
+ flashlight_device_unregister(info->flashlight_dev);
+err_check_hal:
+ return rc;
+}
+
+static int rtfled_remove(struct platform_device *pdev)
+{
+ rt_fled_info_t *info = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ flashlight_device_unregister(info->flashlight_dev);
+ return 0;
+}
+
+static struct platform_driver rt_flash_led_driver = {
+ .driver = {
+ .name = RT_FLED_DEVICE,
+ .owner = THIS_MODULE,
+ },
+ .shutdown = rfled_shutdown,
+ .probe = rtfled_probe,
+ .remove = rtfled_remove,
+};
+
+static int rtfled_init(void)
+{
+ return platform_driver_register(&rt_flash_led_driver);
+}
+subsys_initcall(rtfled_init);
+
+static void rtfled_exit(void)
+{
+ platform_driver_unregister(&rt_flash_led_driver);
+}
+module_exit(rtfled_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com");
+MODULE_VERSION("1.0.0_G");
+MODULE_DESCRIPTION("Richtek Flash LED Driver");
--- /dev/null
+/*include/linux/leds/rtfled.h
+ *Header of Richtek Flash LED Driver
+ *
+ *Copyright (C) 2013 Richtek Technology Corp.
+ *Author: Patrick Chang <patrick_chang@richtek.com>
+ *
+ *This program is free software; you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License version 2 as
+ *published by the Free Software Foundation; either version 2
+ *of the License, or (at your option) any later version.
+ */
+
+#ifndef LINUX_LEDS_RTFLED_H
+#define LINUX_LEDS_RTFLED_H
+#include "flashlight.h"
+
+struct rt_fled_info;
+typedef int (*rt_hal_fled_init) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_suspend) (struct rt_fled_info *info,
+ pm_message_t state);
+typedef int (*rt_hal_fled_resume) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_set_mode) (struct rt_fled_info *info,
+ flashlight_mode_t mode);
+typedef int (*rt_hal_fled_get_mode) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_strobe) (struct rt_fled_info *info);
+
+/*
+ *Return value : -EINVAL => selector parameter is out of range,
+ *otherwise current in uA
+ */
+typedef int (*rt_hal_fled_torch_current_list) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_strobe_current_list) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_timeout_level_list) (struct rt_fled_info *info,
+ int selector);
+/*
+ *Return value : -EINVAL => selector parameter is out of range,
+ *otherwise voltage in mV
+ */
+typedef int (*rt_hal_fled_lv_protection_list) (struct rt_fled_info *info,
+ int selector);
+/*
+ *Return value : -EINVAL => selector parameter is out of range,
+ *otherwise time in ms
+ */
+typedef int (*rt_hal_fled_strobe_timeout_list) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_set_torch_current) (struct rt_fled_info *info,
+ int min_uA, int max_uA,
+ int *selector);
+typedef int (*rt_hal_fled_set_strobe_current) (struct rt_fled_info *info,
+ int min_uA, int max_uA,
+ int *selector);
+typedef int (*rt_hal_fled_set_timeout_level) (struct rt_fled_info *info,
+ int min_uA, int max_uA,
+ int *selector);
+typedef int (*rt_hal_fled_set_lv_protection) (struct rt_fled_info *info,
+ int min_mV, int max_mV,
+ int *selector);
+typedef int (*rt_hal_fled_set_strobe_timeout) (struct rt_fled_info *info,
+ int min_ms, int max_ms,
+ int *selector);
+typedef int (*rt_hal_fled_set_torch_current_sel) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_set_strobe_current_sel) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_set_timeout_level_sel) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_set_lv_protection_sel) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_set_strobe_timeout_sel) (struct rt_fled_info *info,
+ int selector);
+typedef int (*rt_hal_fled_get_torch_current_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_current_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_timeout_level_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_lv_protection_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_timeout_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_torch_current) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_current) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_timeout_level) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_lv_protection) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_timeout) (struct rt_fled_info *info);
+typedef void (*rt_hal_fled_shutdown) (struct rt_fled_info *info);
+
+struct rt_fled_hal {
+ rt_hal_fled_init fled_init;
+ rt_hal_fled_suspend fled_suspend;
+ rt_hal_fled_resume fled_resume;
+ rt_hal_fled_set_mode fled_set_mode;
+ rt_hal_fled_get_mode fled_get_mode;
+ rt_hal_fled_strobe fled_strobe;
+ rt_hal_fled_torch_current_list fled_torch_current_list;
+ rt_hal_fled_strobe_current_list fled_strobe_current_list;
+ rt_hal_fled_timeout_level_list fled_timeout_level_list;
+ rt_hal_fled_lv_protection_list fled_lv_protection_list;
+ rt_hal_fled_strobe_timeout_list fled_strobe_timeout_list;
+ /*method to set */
+ rt_hal_fled_set_torch_current_sel fled_set_torch_current_sel;
+ rt_hal_fled_set_strobe_current_sel fled_set_strobe_current_sel;
+ rt_hal_fled_set_timeout_level_sel fled_set_timeout_level_sel;
+ rt_hal_fled_set_lv_protection_sel fled_set_lv_protection_sel;
+ rt_hal_fled_set_strobe_timeout_sel fled_set_strobe_timeout_sel;
+ /*method to set, optional */
+ rt_hal_fled_set_torch_current fled_set_torch_current;
+ rt_hal_fled_set_strobe_current fled_set_strobe_current;
+ rt_hal_fled_set_timeout_level fled_set_timeout_level;
+ rt_hal_fled_set_lv_protection fled_set_lv_protection;
+ rt_hal_fled_set_strobe_timeout fled_set_strobe_timeout;
+ /*method to get */
+ rt_hal_fled_get_torch_current_sel fled_get_torch_current_sel;
+ rt_hal_fled_get_strobe_current_sel fled_get_strobe_current_sel;
+ rt_hal_fled_get_timeout_level_sel fled_get_timeout_level_sel;
+ rt_hal_fled_get_lv_protection_sel fled_get_lv_protection_sel;
+ rt_hal_fled_get_strobe_timeout_sel fled_get_strobe_timeout_sel;
+ /*method to get, optional */
+ rt_hal_fled_get_torch_current fled_get_torch_current;
+ rt_hal_fled_get_strobe_current fled_get_strobe_current;
+ rt_hal_fled_get_timeout_level fled_get_timeout_level;
+ rt_hal_fled_get_lv_protection fled_get_lv_protection;
+ rt_hal_fled_get_strobe_timeout fled_get_strobe_timeout;
+ /*PM shutdown, optional */
+ rt_hal_fled_shutdown fled_shutdown;
+};
+
+typedef struct rt_fled_info {
+ struct rt_fled_hal *hal;
+ struct flashlight_device *flashlight_dev;
+ const struct flashlight_properties *init_props;
+ char *name;
+ char *chip_name;
+} rt_fled_info_t;
+
+/*Public funtions
+ *argument
+ * @name : Flash LED's name;pass NULL menas "rt-flash-led"
+ */
+
+rt_fled_info_t *rt_fled_get_info_by_name(char *name);
+
+/*Usage :
+ *fled_info = rt_fled_get_info_by_name("FlashLED1");
+ *fled_info->hal->fled_set_strobe_current(fled_info,
+ * 150, 200);
+ */
+
+#endif /*LINUX_LEDS_RTFLED_H */
const char *buf, size_t n)
{
u32 getdata[8];
- u16 regAddr;
+ u8 regAddr;
u8 data;
char cmd;
const char *buftmp = buf;
* R regAddr(8Bit)
* C gpio_name(poweron/powerhold/sleep/boot0/boot1) value(H/L)
*/
- regAddr = (u16)(getdata[0] & 0xff);
- if (strncmp(buf, "start", 5) == 0) {
-
-
- } else if (strncmp(buf, "stop", 4== 0) ){
-
- } else{
- sscanf(buftmp, "%c ", &cmd);
- printk("------zhangqing: get cmd = %c\n", cmd);
- switch(cmd) {
-
- case 'w':
- sscanf(buftmp, "%c %x %x ", &cmd, &getdata[0],&getdata[1]);
- regAddr = (u16)(getdata[0] & 0xff);
- data = (u8)(getdata[1] & 0xff);
- printk("get value = %x\n", data);
-
- rk808_i2c_write(rk808, regAddr, 1, data);
- rk808_i2c_read(rk808, regAddr, 1, &data);
- printk("%x %x\n", getdata[1],data);
-
- break;
-
- case 'r':
- sscanf(buftmp, "%c %x ", &cmd, &getdata[0]);
- printk("CMD : %c %x\n", cmd, getdata[0]);
-
- regAddr = (u16)(getdata[0] & 0xff);
- rk808_i2c_read(rk808, regAddr, 1, &data);
- printk("%x %x\n", getdata[0],data);
-
- break;
+ sscanf(buftmp, "%c ", &cmd);
+ printk("------zhangqing: get cmd = %c\n", cmd);
+ switch (cmd) {
+ case 'w':
+ sscanf(buftmp, "%c %x %x ", &cmd, &getdata[0], &getdata[1]);
+ regAddr = (u8)(getdata[0] & 0xff);
+ data = (u8)(getdata[1] & 0xff);
+ printk("get value = %x\n", data);
+
+ rk808_i2c_write(rk808, regAddr, 1, data);
+ rk808_i2c_read(rk808, regAddr, 1, &data);
+ printk("%x %x\n", getdata[1], data);
+ break;
+ case 'r':
+ sscanf(buftmp, "%c %x ", &cmd, &getdata[0]);
+ printk("CMD : %c %x\n", cmd, getdata[0]);
- default:
- printk("Unknown command\n");
- break;
- }
-}
- return n;
+ regAddr = (u8)(getdata[0] & 0xff);
+ rk808_i2c_read(rk808, regAddr, 1, &data);
+ printk("%x %x\n", getdata[0], data);
+ break;
+ default:
+ printk("Unknown command\n");
+ break;
+ }
+ return n;
}
static ssize_t rk808_test_show(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
u32 getdata[8];
- u16 regAddr;
+ u8 regAddr;
u8 data;
char cmd;
const char *buftmp = buf;
* R regAddr(8Bit)
* C gpio_name(poweron/powerhold/sleep/boot0/boot1) value(H/L)
*/
- regAddr = (u16)(getdata[0] & 0xff);
- if (strncmp(buf, "start", 5) == 0) {
-
-
- } else if (strncmp(buf, "stop", 4== 0) ){
-
- } else{
- sscanf(buftmp, "%c ", &cmd);
- printk("------zhangqing: get cmd = %c\n", cmd);
- switch(cmd) {
-
- case 'w':
- sscanf(buftmp, "%c %x %x ", &cmd, &getdata[0],&getdata[1]);
- regAddr = (u16)(getdata[0] & 0xff);
- data = (u8)(getdata[1] & 0xff);
- printk("get value = %x\n", data);
-
- rk818_i2c_write(rk818, regAddr, 1, data);
- rk818_i2c_read(rk818, regAddr, 1, &data);
- printk("%x %x\n", getdata[1],data);
-
- break;
-
- case 'r':
- sscanf(buftmp, "%c %x ", &cmd, &getdata[0]);
- printk("CMD : %c %x\n", cmd, getdata[0]);
-
- regAddr = (u16)(getdata[0] & 0xff);
- rk818_i2c_read(rk818, regAddr, 1, &data);
- printk("%x %x\n", getdata[0],data);
-
- break;
+ sscanf(buftmp, "%c ", &cmd);
+ printk("------zhangqing: get cmd = %c\n", cmd);
+ switch (cmd) {
+ case 'w':
+ sscanf(buftmp, "%c %x %x ", &cmd, &getdata[0], &getdata[1]);
+ regAddr = (u8)(getdata[0] & 0xff);
+ data = (u8)(getdata[1] & 0xff);
+ printk("get value = %x\n", data);
+
+ rk818_i2c_write(rk818, regAddr, 1, data);
+ rk818_i2c_read(rk818, regAddr, 1, &data);
+ printk("%x %x\n", getdata[1], data);
+ break;
+ case 'r':
+ sscanf(buftmp, "%c %x ", &cmd, &getdata[0]);
+ printk("CMD : %c %x\n", cmd, getdata[0]);
- default:
- printk("Unknown command\n");
- break;
- }
-}
- return n;
+ regAddr = (u8)(getdata[0] & 0xff);
+ rk818_i2c_read(rk818, regAddr, 1, &data);
+ printk("%x %x\n", getdata[0], data);
+ break;
+ default:
+ printk("Unknown command\n");
+ break;
+ }
+ return n;
}
static ssize_t rk818_test_show(struct kobject *kobj, struct kobj_attribute *attr,
#include <linux/mfd/rt5036/rt5036.h>
#include <linux/mfd/rt5036/rt5036-misc.h>
+#include <asm/system_misc.h>
static struct i2c_client *g_shdn;
static bool rt_pm_off;
void rt5036_chip_shutdown(void)
{
- if (g_shdn) {
- rt5036_set_bits(g_shdn, RT5036_REG_MISC3, RT5036_CHIPSHDN_MASK);
- rt5036_clr_bits(g_shdn, RT5036_REG_MISC3, RT5036_CHIPSHDN_MASK);
+ pr_info("%s\n", __func__);
+ if (rt5036_vin_exist()) {
+ arm_pm_restart('h', "charge");
+ } else {
+ if (g_shdn) {
+ pr_info("chip enter shutdown process\n");
+ rt5036_set_bits(g_shdn, RT5036_REG_MISC3,
+ RT5036_CHIPSHDN_MASK);
+ rt5036_clr_bits(g_shdn, RT5036_REG_MISC3,
+ RT5036_CHIPSHDN_MASK);
+ }
}
}
EXPORT_SYMBOL(rt5036_chip_shutdown);
#include <linux/stat.h>
#include <linux/delay.h>
#include <linux/irq.h>
+#include <linux/suspend.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)) {
gpio_cd = slot->cd_gpio;
if (gpio_is_valid(gpio_cd)) {
- gpio_val = gpio_get_value_cansleep(gpio_cd);
+ gpio_val = gpio_get_value(gpio_cd);
msleep(10);
- if (gpio_val == gpio_get_value_cansleep(gpio_cd)) {
- gpio_cd = gpio_get_value_cansleep(gpio_cd) == 0 ? 1 : 0;
+ if (gpio_val == gpio_get_value(gpio_cd)) {
+ gpio_cd = gpio_get_value(gpio_cd) == 0 ? 1 : 0;
if (gpio_cd == 0) {
/* Enable force_jtag wihtout card in slot, ONLY for NCD-package */
grf_writel((0x1 << 24) | (1 << 8), RK312X_GRF_SOC_CON0);
present = dw_mci_get_cd(mmc);
- /* Stop edma when rountine card triggered */
- if(cpu_is_rk3036() || cpu_is_rk312x())
- if(host->dma_ops && host->dma_ops->stop)
- host->dma_ops->stop(host);
-
/* Card insert, switch data line to uart function, and vice verse.
* ONLY audi chip need switched by software, using udbg tag in dts!
*/
present ? "inserted" : "removed.", mmc_hostname(mmc));
dw_mci_ctrl_all_reset(host);
+ /* Stop edma when rountine card triggered */
+ if(cpu_is_rk3036() || cpu_is_rk312x())
+ if(host->dma_ops && host->dma_ops->stop)
+ host->dma_ops->stop(host);
rk_send_wakeup_key();//wake up system
spin_lock_bh(&host->lock);
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
- #if 0
- if (mmc->ops->card_event)
- mmc->ops->card_event(mmc);
-
- mmc_detect_change(mmc, msecs_to_jiffies(200));
- #endif
-
/* wakeup system whether gpio debounce or not */
rk_send_wakeup_key();
- queue_work(host->card_workqueue, &host->card_work);
- return IRQ_HANDLED;
+
+ /* no need to trigger detect flow when rescan is disabled.
+ This case happended in dpm, that we just wakeup system and
+ let suspend_post notify callback handle it.
+ */
+ if(mmc->rescan_disable == 0)
+ queue_work(host->card_workqueue, &host->card_work);
+ else
+ printk("%s: rescan been disabled!\n", __FUNCTION__);
+
+ return IRQ_HANDLED;
}
static void dw_mci_of_set_cd_gpio_irq(struct device *dev, u32 gpio,
dev_warn(host->dev, "%s: No udbg pinctrl found!\n",
mmc_hostname(host->mmc));
} else {
- if (pinctrl_select_state(host->pinctrl, host->pins_udbg) < 0)
- dev_err(host->dev, "%s: Udbg pinctrl setting failed!\n",
- mmc_hostname(host->mmc));
+ if (!dw_mci_get_cd(host->mmc))
+ if (pinctrl_select_state(host->pinctrl, host->pins_udbg) < 0)
+ dev_err(host->dev, "%s: Udbg pinctrl setting failed!\n",
+ mmc_hostname(host->mmc));
}
}
}
+static int dw_mci_pm_notify(struct notifier_block *notify_block,
+ unsigned long mode, void *unused)
+{
+ struct mmc_host *host = container_of(
+ notify_block, struct mmc_host, pm_notify);
+ unsigned long flags;
+
+ switch (mode) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ dev_err(host->parent, "dw_mci_pm_notify: suspend prepare\n");
+ spin_lock_irqsave(&host->lock, flags);
+ host->rescan_disable = 1;
+ spin_unlock_irqrestore(&host->lock, flags);
+ if (cancel_delayed_work(&host->detect))
+ wake_unlock(&host->detect_wake_lock);
+ break;
+
+ case PM_POST_SUSPEND:
+ case PM_POST_HIBERNATION:
+ case PM_POST_RESTORE:
+ dev_err(host->parent, "dw_mci_pm_notify: post suspend\n");
+ spin_lock_irqsave(&host->lock, flags);
+ host->rescan_disable = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+ mmc_detect_change(host, 10);
+ }
+
+ return 0;
+}
static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
{
if (of_find_property(host->dev->of_node, "supports-tSD", NULL))
mmc->restrict_caps |= RESTRICT_CARD_TYPE_TSD;
+ if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
+ mmc->pm_notify.notifier_call = dw_mci_pm_notify;
+ if (register_pm_notifier(&mmc->pm_notify)) {
+ printk(KERN_ERR "dw_mci: register_pm_notifier failed\n");
+ goto err_pm_notifier;
+ }
+ }
/* We assume only low-level chip use gpio_cd */
if (cpu_is_rk312x() &&
slot->last_detect_state = 1;
return 0;
+err_pm_notifier:
+ unregister_pm_notifier(&mmc->pm_notify);
err_setup_bus:
if (gpio_is_valid(slot->cd_gpio))
static void dw_mci_dealwith_timeout(struct dw_mci *host)
{
u32 regs;
- u32 sdio_int;
+ u32 sdio_int;
+ dev_err(host->dev, "host->state = 0x%x\n", host->state);
switch(host->state){
case STATE_IDLE:
break;
mci_writel(host, RINTSTS, SDMMC_INT_DRTO); // clear interrupt
set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
host->state = STATE_DATA_BUSY;
- if (!dw_mci_ctrl_all_reset(host)) {
- return ;
+ if (!dw_mci_ctrl_all_reset(host)) {
+ dev_err(host->dev, "dto: ctrl_all_reset failed!\n");
+ return ;
}
/* NO requirement to reclaim slave chn using external dmac */
enable_irq(host->irq);
}
-
-void resume_rescan_enable(struct work_struct *work)
-{
- struct dw_mci *host =
- container_of(work, struct dw_mci, resume_rescan.work);
- host->mmc->rescan_disable = 0;
- mmc_detect_change(host->mmc, 10);
-}
-
-
int dw_mci_probe(struct dw_mci *host)
{
const struct dw_mci_drv_data *drv_data = host->drv_data;
spin_lock_init(&host->slock);
INIT_LIST_HEAD(&host->queue);
- INIT_DELAYED_WORK(&host->resume_rescan, resume_rescan_enable);
/*
* Get the host data width - this assumes that HCON has been set with
* the correct values.
int i;
del_timer_sync(&host->dto_timer);
- cancel_delayed_work(&host->resume_rescan);
mci_writel(host, RINTSTS, 0xFFFFFFFF);
mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
mci_writel(host, CLKSRC, 0);
destroy_workqueue(host->card_workqueue);
+ if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)
+ unregister_pm_notifier(&host->mmc->pm_notify);
if(host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
/*only for sdmmc controller*/
if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
- host->mmc->rescan_disable = 1;
-
- if(cancel_delayed_work(&host->mmc->detect))
- wake_unlock(&host->mmc->detect_wake_lock);
-
disable_irq(host->irq);
if (pinctrl_select_state(host->pinctrl, host->pins_idle) < 0)
MMC_DBG_ERR_FUNC(host->mmc, "Idle pinctrl setting failed! [%s]",
if(pinctrl_select_state(host->pinctrl, host->pins_default) < 0)
MMC_DBG_ERR_FUNC(host->mmc, "Default pinctrl setting failed! [%s]",
mmc_hostname(host->mmc));
- host->mmc->rescan_disable = 1;
+
/* Disable jtag*/
if(cpu_is_rk3288())
grf_writel(((1 << 12) << 16) | (0 << 12), RK3288_GRF_SOC_CON0);
}
}
- if((host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD))
- schedule_delayed_work(&host->resume_rescan, msecs_to_jiffies(2000));
-
return 0;
}
EXPORT_SYMBOL(dw_mci_resume);
DNGL_FUNC(dhd_cfg80211_down, (wl));
wl_flush_eq(wl);
wl_link_down(wl);
- if (wl->p2p_supported)
- wl_cfgp2p_down(wl);
+ //if (wl->p2p_supported)
+ // wl_cfgp2p_down(wl);
dhd_monitor_uninit();
return err;
#define CONFIG_LAYER2_ROAMING
#define CONFIG_LAYER2_ROAMING_RESUME
//#define CONFIG_ADAPTOR_INFO_CACHING_FILE // now just applied on 8192cu only, should make it general...
-//#define CONFIG_RESUME_IN_WORKQUEUE
+#define CONFIG_RESUME_IN_WORKQUEUE
//#define CONFIG_SET_SCAN_DENY_TIMER
#define CONFIG_LONG_DELAY_ISSUE
#define CONFIG_NEW_SIGNAL_STAT_PROCESS
#define USB_INTERFERENCE_ISSUE // this should be checked in all usb interface
//#define CONFIG_ADAPTOR_INFO_CACHING_FILE // now just applied on 8192cu only, should make it general...
-//#define CONFIG_RESUME_IN_WORKQUEUE
+#define CONFIG_RESUME_IN_WORKQUEUE
//#define CONFIG_SET_SCAN_DENY_TIMER
#define CONFIG_LONG_DELAY_ISSUE
#define CONFIG_NEW_SIGNAL_STAT_PROCESS
#define CONFIG_LAYER2_ROAMING
#define CONFIG_LAYER2_ROAMING_RESUME
//#define CONFIG_ADAPTOR_INFO_CACHING_FILE // now just applied on 8192cu only, should make it general...
-//#define CONFIG_RESUME_IN_WORKQUEUE
+#define CONFIG_RESUME_IN_WORKQUEUE
//#define CONFIG_SET_SCAN_DENY_TIMER
#define CONFIG_LONG_DELAY_ISSUE
#define CONFIG_NEW_SIGNAL_STAT_PROCESS
#define RICOH619_OCV_OFFSET_BOUND 3
#define RICOH619_OCV_OFFSET_RATIO 2
-#define RICOH619_VADP_DROP_WORK 1
+#define RICOH619_VADP_DROP_WORK
#define RICOH619_TIME_CHG_STEP (1*HZ)// unit:secound
#define RICOH619_TIME_CHG_COUNT 15*60//only for test //15*60
j = info->soca->soc - info->soca->soc/1000*1000;
Ocv_now_table = ocv_table[i]*100+(ocv_table[i+1]-ocv_table[i])*j/10;
- Rsys_now = (info->soca->Vsys_ave - Ocv_now_table) / info->soca->Ibat_ave;
+ Rsys_now = (info->soca->Vsys_ave - Ocv_now_table) / info->soca->Ibat_ave;
+ if (((abs(info->soca->soc - info->soca->displayed_soc)) > 10)
+ && (info->soca->Ibat_ave > -250)) {
+ if (Rsys_now < 0)
+ Rsys_now = max(-info->soca->Rbat, Rsys_now);
+ else
+ Rsys_now = min(info->soca->Rbat, Rsys_now);
+ }
Ocv_ZeroPer_now = info->soca->target_vsys * 1000 - Ibat_now * Rsys_now;
FA_CAP_now = fa_cap * ((10000 - start_per) / 100 ) / 100;
- RICOH_FG_DBG("PMU: ------- Target_Cutoff_Vol= %d: Ocv_ZeroPer_now= %d: start_per= %d =======\n",
- Target_Cutoff_Vol, Ocv_ZeroPer_now, start_per);
+ RICOH_FG_DBG("PMU: -------Ocv_ZeroPer_now= %d: start_per= %d =======\n",
+ Ocv_ZeroPer_now, start_per);
/* get RE_CAP_now */
RE_CAP_now = FA_CAP_now - use_cap;
info->soca->last_displayed_soc = info->soca->displayed_soc+50;
- if((info->soca->displayed_soc >= 9850) && (info->soca->Ibat_ave > -20) && (info->capacity < 100))
+ if ((info->soca->displayed_soc >= 9850) && (info->soca->Ibat_ave > -20) && (info->capacity < 100)
+ && (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING))
{
if(info->chg_complete_rd_flag == 0)
{
RICOH_FG_DBG("info->chg_complete_rd_cnt = %d\n", info->chg_complete_rd_cnt);
RICOH_FG_DBG("info->chg_complete_rd_flag = %d\n", info->chg_complete_rd_flag);
RICOH_FG_DBG("info->chg_complete_tm_ov_flag = %d\n", info->chg_complete_tm_ov_flag);
- RICOH_FG_DBG("time_ov_flag = %d\n", time_ov_flag);
if(info->chg_complete_rd_flag == 1)
{
}
}
- if(time_ov_flag == 0)
+ if ((time_ov_flag == 0) && (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING))
{
info->chg_complete_rd_cnt++;
queue_delayed_work(info->monitor_wqueue, &info->charge_complete_ready,
}
else
{
- time_ov_flag = 0;
+ info->chg_complete_rd_flag = 0;
}
RICOH_FG_DBG("PMU2: %s return\n", __func__);
ricoh619_write(info->dev->parent, CHGISET_REG, 0xD3);
}
#endif
- }
- else if (reg_val & 0x80) { /* USE USB */
+ } else if (reg_val & 0x80) { /* USE ONLY USB */
queue_work(info->usb_workqueue, &info->usb_irq_work);
}
}
{
struct ricoh619_battery_info *info = container_of(work,
struct ricoh619_battery_info, usb_irq_work);
- int ret = 0,i;
+ int ret = 0;
uint8_t sts;
RICOH_FG_DBG("PMU:%s In\n", __func__);
dev_err(info->dev, "Error in reading the control register\n");
sts &= 0x02;
- if (sts) {
- for(i =0;i<60;i++){
+ if (sts)
ricoh619_usb_charge_det();
- mdelay(10);
- }
- } else {
- /*********************/
- /* No process ?? */
- /*********************/
- }
RICOH_FG_DBG("PMU:%s Out\n", __func__);
}
#ifdef ENABLE_LOW_BATTERY_DETECTION
cancel_delayed_work(&info->low_battery_work);
#endif
- cancel_delayed_work(&info->charge_complete_ready);
+/* cancel_delayed_work(&info->charge_complete_ready);*/
#ifdef ENABLE_FACTORY_MODE
cancel_delayed_work(&info->factory_mode_work);
#endif
#ifdef RICOH619_VADP_DROP_WORK
cancel_delayed_work(&info->vadp_drop_work);
#endif
- info->chg_complete_rd_cnt = 0;
- info->chg_complete_rd_flag = 0;
+/* info->chg_complete_rd_cnt = 0;*/
+/* info->chg_complete_rd_flag = 0;*/
if(info->capacity == 100)
{
printk("chg_complete_rd_cnt suspend: %d\n", info->chg_complete_rd_cnt);
info->chg_complete_rd_cnt += (tv.tv_sec - ts_suspend.tv_sec);
printk("chg_complete_rd_cnt resume: %d\n", info->chg_complete_rd_cnt);
- cancel_delayed_work(&info->charge_complete_ready);
+ flush_work(&info->charge_complete_ready.work);
}
RICOH_FG_DBG(KERN_INFO "PMU: %s: \n", __func__);
info->soca->displayed_soc = -EINVAL;
} else if (RICOH619_SOCA_ZERO == info->soca->status) {
if (calc_ocv(info) > get_OCV_voltage(info, 0)) {
+ RICOH_FG_DBG(KERN_INFO "PMU: %s: RICOH619_SOCA_ZERO if ()...\n", __func__);
ret = ricoh619_read(info->dev->parent, PSWR_REG, &val);
val &= 0x7f;
info->soca->soc = val * 100;
dev_err(info->dev, "Error in writing the control register\n");
info->soca->status = RICOH619_SOCA_FG_RESET;
- } else
- info->soca->displayed_soc = 0;
+ } else {
+ RICOH_FG_DBG(KERN_INFO "PMU: %s: RICOH619_SOCA_ZERO else()...\n", __func__);
+ /*info->soca->displayed_soc = 0;*/
+ info->soca->displayed_soc = info->soca->suspend_soc;
+ }
} else {
info->soca->soc = info->soca->suspend_soc;
return charge_level;
}
+
+static int rk_adc_battery_iio_read_refvol(struct rk30_adc_battery_platform_data *data)
+{
+ struct iio_channel *channel = data->ref_voltage_chan;
+ int val, ret;
+
+ ret = iio_read_channel_raw(channel, &val);
+ if (ret < 0) {
+ pr_err("read channel() error: %d\n", ret);
+ return ret;
+ }
+ return val;
+}
+
+static int get_ref_voltage(struct rk30_adc_battery_data *bat)
+{
+ int data_value;
+ struct regulator *logic;
+ int voltage, ref_voltage;
+
+ logic = regulator_get(NULL, "vdd_arm");
+ voltage = regulator_get_voltage(logic);
+ data_value = rk_adc_battery_iio_read_refvol(bat->pdata);
+ ref_voltage = voltage*1024/data_value/1000;
+
+ return ref_voltage;
+}
static int rk_adc_voltage(struct rk30_adc_battery_data *bat, int value)
{
int voltage;
-
- int ref_voltage; //reference_voltage
- int pullup_res;
- int pulldown_res;
+ int ref_voltage;
ref_voltage = bat ->pdata->reference_voltage;
- pullup_res = bat ->pdata->pull_up_res;
- pulldown_res = bat ->pdata->pull_down_res;
-
- if(ref_voltage && pullup_res && pulldown_res){
-#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026)
- ref_voltage = adc_get_curr_ref_volt();
-#endif
- voltage = ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res));
- DBG("ref_voltage =%d, voltage=%d \n", ref_voltage,voltage);
+
+ if (ref_voltage) {
+ if (bat->pdata->auto_calibration == 1)
+ ref_voltage = get_ref_voltage(bat);
+ voltage = (value * ref_voltage * (batt_table[4] + batt_table[5])) / (1024 * batt_table[5]);
+ DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
}else{
-#if 0
- if(bat ->capacitytmp < 5)
- ref_voltage = adc_get_curr_ref_volt();
- else
- ref_voltage = adc_get_def_ref_volt();
-#endif
-#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026)
- ref_voltage = adc_get_curr_ref_volt();
- voltage = (value * ref_voltage * (batt_table[4] +batt_table[5])) / (1024 *batt_table[5]);
-#else
voltage = adc_to_voltage(value);
-#endif
}
-
- DBG("ref_voltage =%d, voltage=%d \n", ref_voltage,voltage);
+ DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
return voltage;
}
}
else if (bat ->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
//chargeing state
-
- if( bat ->pdata->is_reboot_charging == 1)
- bat ->bat_capacity = (old_capacity < 10) ?(old_capacity+2):old_capacity;
- else
- bat ->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+ bat->bat_capacity = (old_capacity < 10) ? (old_capacity + 2) : old_capacity;
}else{
- if(new_capacity > old_capacity + 50 )
bat ->bat_capacity = old_capacity + 5;
- else
- bat ->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity; //avoid the value of capacity increase
if(bat->bat_capacity == 100)
bat->bat_capacity = 99;
if(bat->bat_capacity == 0)
int ret;
int i;
size_t size;
- struct iio_channel *chan;
- if (!node)
- return -ENODEV;
+ struct iio_channel *channels;
+ int num = 0;
+
+ channels = iio_channel_get_all(&pdev->dev);
+ if (IS_ERR(channels))
+ pr_err("get adc channels fails\n");
+ while (channels[num].indio_dev)
+ num++;
+ data->chan = &channels[0];
+ if (num > 1)
+ data->ref_voltage_chan = &channels[1];
+ ret = of_property_read_u32(node, "auto_calibration", &value);
+ if (ret < 0) {
+ pr_info("%s:unsupport auto_calibration\n", __func__);
+ value = 0;
+ }
+ data->auto_calibration = value;
- chan = iio_channel_get(&pdev->dev, NULL);
- if (IS_ERR(chan))
- pr_err("iio_channel_get fail\n");
- data->chan = chan;
+ ret = of_property_read_u32(node, "ref_voltage", &value);
+ if (ret < 0) {
+ pr_info("%s:unsupport ref_voltage\n", __func__);
+ value = 0;
+ }
+ data->reference_voltage = value;
/* determine the number of config info */
prop = of_find_property(node, "bat_table", &length);
#define PWMCR_MIN_PRESCALE 0x00
#define PWMCR_MAX_PRESCALE 0x07
-#define PWMDCR_MIN_DUTY 0x0001
+#define PWMDCR_MIN_DUTY 0x0000
#define PWMDCR_MAX_DUTY 0xFFFF
#define PWMPCR_MIN_PERIOD 0x0001
pr_err("%s: failure mapping buffer to userspace\n",
__func__);
+ trace_ion_buffer_mmap("", (unsigned int)buffer, buffer->size,
+ vma->vm_start, vma->vm_end);
+
return ret;
}
+int ion_munmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+ struct ion_buffer *buffer = dmabuf->priv;
+
+ trace_ion_buffer_munmap("", (unsigned int)buffer, buffer->size,
+ vma->vm_start, vma->vm_end);
+
+ return 0;
+}
+
static void ion_dma_buf_release(struct dma_buf *dmabuf)
{
struct ion_buffer *buffer = dmabuf->priv;
TP_PROTO(const char* client, void* buffer, unsigned int size, void* kaddr),
TP_ARGS(client, buffer, size, kaddr));
+DECLARE_EVENT_CLASS(ion_mmap_op,
+ TP_PROTO(const char* client, unsigned int buf, unsigned int size,
+ unsigned long vm_start, unsigned long vm_end),
+ TP_ARGS(client, buf, size, vm_start, vm_end),
+ TP_STRUCT__entry(
+ __string(client, client)
+ __field(unsigned int, buf)
+ __field(unsigned int, size)
+ __field(unsigned long, vm_start)
+ __field(unsigned long, vm_end)
+ ),
+ TP_fast_assign(
+ __assign_str(client, client);
+ __entry->buf = buf;
+ __entry->size = size;
+ __entry->vm_start = vm_start;
+ __entry->vm_end = vm_end;
+ ),
+ TP_printk("client=%s,buffer=%08x:%d,vma[%08lx:%08lx]",
+ __get_str(client), __entry->buf, __entry->size,
+ __entry->vm_start, __entry->vm_end)
+);
+
+DEFINE_EVENT(ion_mmap_op, ion_buffer_mmap,
+ TP_PROTO(const char* client, unsigned int buf, unsigned int size,
+ unsigned long vm_start, unsigned long vm_end),
+ TP_ARGS(client, buf, size, vm_start, vm_end));
+DEFINE_EVENT(ion_mmap_op, ion_buffer_munmap,
+ TP_PROTO(const char* client, unsigned int buf, unsigned int size,
+ unsigned long vm_start, unsigned long vm_end),
+ TP_ARGS(client, buf, size, vm_start, vm_end));
#endif /* _TRACE_ION_H */
#include "dwc_otg_core_if.h"
#include "dwc_otg_pcd_if.h"
#include "dwc_otg_hcd_if.h"
+#include "dwc_otg_regs.h"
+#include "dwc_otg_cil.h"
+#include "usbdev_rk.h"
/*
* MACROs for defining sysfs attribute
struct device_attribute *attr,
const char *buf, size_t count)
{
-
dwc_otg_device_t *otg_dev = _dev->platform_data;
+ struct dwc_otg_platform_data *pldata = otg_dev->pldata;
uint32_t on = simple_strtoul(buf, NULL, 16);
+
+ if (on != 0 && on != 1)
+ return -EINVAL;
+
dwc_otg_set_prtpower(otg_dev->core_if, on);
+ pldata->power_enable(on);
return count;
}
#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
+static int test_sq(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0 = { .d32 = 0 };
+ dctl_data_t dctl = { .d32 = 0 };
+ dsts_data_t dsts = { .d32 = 0 };
+
+ /**
+ * Step.1 check current mode
+ * Step.2 check connection
+ * Step.3 enter test packet mode
+ */
+
+ if (dwc_otg_is_host_mode(core_if)) {
+ DWC_PRINTF("Host Mode\n");
+ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
+
+ if (hprt0.b.prtena && !hprt0.b.prtsusp &&
+ hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) {
+ hprt0.d32 = 0;
+ hprt0.b.prttstctl = 0x4;
+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
+ DWC_PRINTF("Start packet test\n");
+ return 0;
+
+ } else
+ DWC_PRINTF("Invalid connect status HPRT0 = 0x%08x\n",
+ hprt0.d32);
+ } else {
+ DWC_PRINTF("Device Mode\n");
+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
+
+ if (!dsts.b.suspsts &&
+ dsts.b.enumspd == DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ) {
+ dctl.b.tstctl = 0x4;
+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
+ dctl.d32);
+ DWC_PRINTF("Start packet test\n");
+ return 0;
+
+ } else
+ DWC_PRINTF("Invalid connect status DSTS = 0x%08x\n",
+ dsts.d32);
+ }
+
+ return -1;
+
+}
+
+/**
+* Show the usage of usb controler test_sq attribute.
+*/
+static ssize_t test_sq_show(struct device *_dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf,
+ "USAGE : echo anything to \"test\" to start test packet pattern\n");
+}
+
+static ssize_t test_sq_store(struct device *_dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+
+{
+ dwc_otg_device_t *otg_dev = _dev->platform_data;
+ struct dwc_otg_platform_data *pldata = otg_dev->pldata;
+
+ if (pldata->phy_status == USB_PHY_SUSPEND) {
+ DWC_PRINTF("Invalid status : SUSPEND\n");
+ return -EBUSY;
+ }
+
+ if (test_sq(otg_dev->core_if))
+ return -EBUSY;
+ else
+ return count;
+}
+
+DEVICE_ATTR(test_sq, S_IWUSR | S_IRUSR, test_sq_show, test_sq_store);
+
/**@}*/
/**
error = device_create_file(&dev->dev, &dev_attr_besl_reject);
error = device_create_file(&dev->dev, &dev_attr_hird_thres);
#endif
+ error = device_create_file(&dev->dev, &dev_attr_test_sq);
}
/**
device_remove_file(&dev->dev, &dev_attr_besl_reject);
device_remove_file(&dev->dev, &dev_attr_hird_thres);
#endif
+ device_remove_file(&dev->dev, &dev_attr_test_sq);
}
DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
/* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
Host mode ISOC in issue fix - vahrama */
- ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16;
+ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR8;
core_if->dma_enable = (core_if->core_params->dma_enable != 0);
core_if->dma_desc_enable =
(core_if->core_params->dma_desc_enable != 0);
DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
/* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
Host mode ISOC in issue fix - vahrama */
- ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16;
+ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR8;
core_if->dma_enable = (core_if->core_params->dma_enable != 0);
core_if->dma_desc_enable =
(core_if->core_params->dma_desc_enable != 0);
DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
dwc_udelay(10);
- gahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16;
+ gahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR8;
DWC_MODIFY_REG32(&global_regs->gahbcfg, 0, gahbcfg.b.hburstlen);
/* Device configuration register */
};
#endif
-#ifdef CONFIG_RK_USB_UART
static u32 usb_to_uart_status;
-#endif
/*-------------------------------------------------------------------------*/
/* Encapsulate the module parameter settings */
struct dwc_otg_platform_data *pldata_otg;
struct dwc_otg_platform_data *pldata_host;
struct rkehci_platform_data *pldata_ehci;
-
+ if (cpu_is_rk312x()) {
+ pldata_otg = &usb20otg_pdata_rk3126;
+ if (usb_to_uart_status)
+ pldata_otg->dwc_otg_uart_mode(pldata_otg, PHY_UART_MODE);
+ }
if (cpu_is_rk3288()) {
#ifdef CONFIG_RK_USB_UART
/* enable USB bypass UART function */
struct dwc_otg_platform_data *pldata_host;
struct rkehci_platform_data *pldata_ehci;
+ if (cpu_is_rk312x()) {
+ pldata_otg = &usb20otg_pdata_rk3126;
+ usb_to_uart_status = pldata_otg->get_status(USB_STATUS_UARTMODE);
+ pldata_otg->dwc_otg_uart_mode(pldata_otg, PHY_USB_MODE);
+ }
if (cpu_is_rk3288()) {
#ifdef CONFIG_RK_USB_UART
/* disable USB bypass UART function */
/* id in grf */
ret = soc_status0 & (0x1 << 8);
break;
+ case USB_STATUS_UARTMODE:
+ ret = readl(RK_GRF_VIRT + RK312X_GRF_UOC1_CON4) & (1 << 12);
+ break;
case USB_CHIP_ID:
ret = control_usb->chip_id;
break;
{
if (0 == enable) {
/* disable host_drv power */
- /* do not disable power in default */
+ if (gpio_is_valid(control_usb->host_gpios->gpio))
+ gpio_set_value(control_usb->host_gpios->gpio, 0);
} else if (1 == enable) {
/* enable host_drv power */
if (gpio_is_valid(control_usb->host_gpios->gpio))
obj-$(CONFIG_USB_EHCI_HCD_SYNOPSYS) += ehci-h20ahb.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
+obj-$(CONFIG_USB_EHCI_RK) += ehci-rockchip.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
#define PLATFORM_DRIVER ehci_hcd_tilegx_driver
#endif
-#ifdef CONFIG_USB_EHCI_RK
-#include "ehci-rockchip.c"
-#define PLATFORM_DRIVER ehci_rk_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_RKHSIC
#include "ehci-rkhsic.c"
#define ROCKCHIP_PLATFORM_DRIVER ehci_rkhsic_driver
# include <linux/device.h>
# include <linux/of.h>
# include <linux/of_platform.h>
-# include "ehci.h"
+# include <linux/usb.h>
+# include <linux/usb/hcd.h>
+# include <linux/usb/otg.h>
+
# include "../dwc_otg_310/usbdev_rk.h"
+# include "ehci.h"
static int rkehci_status = 1;
-static struct ehci_hcd *g_ehci;
+static struct hc_driver rk_ehci_hc_driver;
+
struct rk_ehci_hcd {
struct ehci_hcd *ehci;
uint8_t host_enabled;
{},
};
-static void ehci_port_power(struct ehci_hcd *ehci, int is_on)
-{
- unsigned port;
-
- if (!HCS_PPC(ehci->hcs_params))
- return;
-
- ehci_dbg(ehci, "...power%s ports...\n", is_on ? "up" : "down");
- for (port = HCS_N_PORTS(ehci->hcs_params); port > 0;)
- (void)ehci_hub_control(ehci_to_hcd(ehci),
- is_on ? SetPortFeature :
- ClearPortFeature, USB_PORT_FEAT_POWER,
- port--, NULL, 0);
- /* Flush those writes */
- ehci_readl(ehci, &ehci->regs->command);
- msleep(20);
-}
-
static void rk_ehci_hcd_enable(struct work_struct *work)
{
struct rk_ehci_hcd *rk_ehci;
hcd = ehci_to_hcd(ehci);
if (rk_ehci->host_enabled == rk_ehci->host_setenable) {
- printk("%s, enable flag %d\n", __func__,
+ EHCI_PRINT("%s, enable flag %d\n", __func__,
rk_ehci->host_setenable);
goto out;
}
goto out;
}
- printk("%s, disable host controller\n", __func__);
- ehci_port_power(ehci, 0);
+ EHCI_PRINT("%s, disable host controller\n", __func__);
usb_remove_hcd(hcd);
/* reset cru and reinitialize EHCI controller */
if (pldata->phy_suspend)
pldata->phy_suspend(pldata, USB_PHY_ENABLED);
mdelay(5);
- ehci_port_power(ehci, 1);
- printk("%s, enable host controller\n", __func__);
+ EHCI_PRINT("%s, enable host controller\n", __func__);
}
rk_ehci->host_enabled = rk_ehci->host_setenable;
return;
}
-static struct hc_driver rk_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "Rockchip On-Chip EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_USB2 | HCD_MEMORY,
-
- .reset = ehci_init,
- .start = ehci_run,
-
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- /*
- * PM support
- */
-#ifdef CONFIG_PM
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
-};
-
static ssize_t ehci_power_show(struct device *_dev,
struct device_attribute *attr, char *buf)
{
{
uint32_t val = simple_strtoul(buf, NULL, 16);
struct usb_hcd *hcd = dev_get_drvdata(_dev);
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct rkehci_platform_data *pldata = _dev->platform_data;
+ struct rk_ehci_hcd *rk_ehci = (struct rk_ehci_hcd *)hcd_to_ehci(hcd)->priv;
- printk("%s: %d setting to: %d\n", __func__, rkehci_status, val);
+ EHCI_PRINT("%s: %d setting to: %d\n", __func__, rkehci_status, val);
if (val == rkehci_status)
goto out;
rkehci_status = val;
switch (val) {
case 0: /* power down */
- ehci_port_power(ehci, 0);
+ rk_ehci->host_enabled = 0;
msleep(5);
usb_remove_hcd(hcd);
break;
case 1: /* power on */
pldata->soft_reset(pldata, RST_POR);
usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);
- ehci_port_power(ehci, 1);
+ rk_ehci->host_enabled = 2;
break;
default:
break;
static DEVICE_ATTR(ehci_power, S_IRUGO | S_IWUSR, ehci_power_show,
ehci_power_store);
-static ssize_t debug_show(struct device *_dev, struct device_attribute *attr,
+static ssize_t debug_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct ehci_hcd *ehci = hcd_to_ehci(dev_get_drvdata(dev));
volatile uint32_t *addr;
EHCI_PRINT("******** EHCI Capability Registers **********\n");
- addr = &g_ehci->caps->hc_capbase;
- EHCI_PRINT("HCIVERSION / CAPLENGTH @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->caps->hcs_params;
- EHCI_PRINT("HCSPARAMS @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->caps->hcc_params;
- EHCI_PRINT("HCCPARAMS @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
+ addr = &ehci->caps->hc_capbase;
+ EHCI_PRINT("HCIVERSION / CAPLENGTH @0z%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->caps->hcs_params;
+ EHCI_PRINT("HCSPARAMS @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->caps->hcc_params;
+ EHCI_PRINT("HCCPARAMS @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
EHCI_PRINT("********* EHCI Operational Registers *********\n");
- addr = &g_ehci->regs->command;
- EHCI_PRINT("USBCMD @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->status;
- EHCI_PRINT("USBSTS @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->intr_enable;
- EHCI_PRINT("USBINTR @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->frame_index;
- EHCI_PRINT("FRINDEX @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->segment;
- EHCI_PRINT("CTRLDSSEGMENT @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->frame_list;
- EHCI_PRINT("PERIODICLISTBASE @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->async_next;
- EHCI_PRINT("ASYNCLISTADDR @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = &g_ehci->regs->configured_flag;
- EHCI_PRINT("CONFIGFLAG @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
- addr = g_ehci->regs->port_status;
- EHCI_PRINT("PORTSC @0x%08x: 0x%08x\n",
- (uint32_t) addr, readl_relaxed(addr));
+ addr = &ehci->regs->command;
+ EHCI_PRINT("USBCMD @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->status;
+ EHCI_PRINT("USBSTS @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->intr_enable;
+ EHCI_PRINT("USBINTR @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->frame_index;
+ EHCI_PRINT("FRINDEX @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->segment;
+ EHCI_PRINT("CTRLDSSEGMENT @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->frame_list;
+ EHCI_PRINT("PERIODICLISTBASE @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->async_next;
+ EHCI_PRINT("ASYNCLISTADDR @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->configured_flag;
+ EHCI_PRINT("CONFIGFLAG @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
+ addr = &ehci->regs->port_status[0];
+ EHCI_PRINT("PORTSC @0x%p: 0x%08x\n",
+ addr, readl_relaxed(addr));
return sprintf(buf, "EHCI Registers Dump\n");
}
static DEVICE_ATTR(debug_ehci, S_IRUGO, debug_show, NULL);
+static int test_sq(struct ehci_hcd *ehci)
+{
+ u32 portc = readl(&ehci->regs->port_status);
+
+ if ((portc & PORT_PE) && !(portc & PORT_SUSPEND)) {
+ writel(PORT_TEST_PKT, &ehci->regs->port_status);
+ EHCI_PRINT("Start packet test\n");
+ return 0;
+
+ } else
+ EHCI_PRINT("Invalid connect status PORTC = 0x%08x\n", portc);
+
+ return -1;
+}
+
+static ssize_t test_sq_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+
+{
+ struct rkehci_platform_data *pldata = dev->platform_data;
+ struct ehci_hcd *ehci = hcd_to_ehci(dev_get_drvdata(dev));
+
+ if (pldata->phy_status == USB_PHY_SUSPEND) {
+ EHCI_PRINT("Invalid status : SUSPEND\n");
+ return -EBUSY;
+ }
+
+ return (test_sq(ehci)) ? -EBUSY : count;
+}
+
+static DEVICE_ATTR(test_sq, S_IWUSR, NULL, test_sq_store);
+
static struct of_device_id rk_ehci_of_match[] = {
{
.compatible = "rockchip,rk3288_rk_ehci_host",
struct device *dev = &pdev->dev;
struct rkehci_platform_data *pldata;
int ret;
- int retval = 0;
- static u64 usb_dmamask = 0xffffffffUL;
struct device_node *node = pdev->dev.of_node;
struct rkehci_pdata_id *p;
struct rk_ehci_hcd *rk_ehci;
const struct of_device_id *match =
of_match_device(of_match_ptr(rk_ehci_of_match), &pdev->dev);
- dev_dbg(&pdev->dev, "ehci_rk proble\n");
+ dev_dbg(&pdev->dev, "ehci_rk probe!\n");
if (match) {
p = (struct rkehci_pdata_id *)match->data;
return -EINVAL;
}
- dev->dma_mask = &usb_dmamask;
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+ if (!pdev->dev.coherent_dma_mask)
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+ device_create_file(dev, &dev_attr_ehci_power);
+ device_create_file(dev, &dev_attr_debug_ehci);
+ device_create_file(dev, &dev_attr_test_sq);
- retval = device_create_file(dev, &dev_attr_ehci_power);
- retval = device_create_file(dev, &dev_attr_debug_ehci);
hcd =
usb_create_hcd(&rk_ehci_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
hcd->regs = devm_ioremap_resource(dev, res);
-
if (!hcd->regs) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + 0x10;
- printk("%s %p %p\n", __func__, ehci->caps, ehci->regs);
-
- dbg_hcs_params(ehci, "reset");
- dbg_hcc_params(ehci, "reset");
+ EHCI_PRINT("%s %p %p\n", __func__, ehci->caps, ehci->regs);
ehci->hcs_params = readl(&ehci->caps->hcs_params);
goto put_hcd;
}
- g_ehci = ehci;
+ rk_ehci = (struct rk_ehci_hcd *)hcd_to_ehci(hcd)->priv;
- rk_ehci = devm_kzalloc(&pdev->dev, sizeof(struct rk_ehci_hcd),
- GFP_KERNEL);
if (!rk_ehci) {
ret = -ENOMEM;
goto put_hcd;
mod_timer(&rk_ehci->connect_detect_timer, jiffies + (HZ << 1));
INIT_DELAYED_WORK(&rk_ehci->host_enable_work, rk_ehci_hcd_enable);
- ehci_port_power(ehci, 0);
-
if (pldata->phy_suspend) {
if (pldata->phy_status == USB_PHY_ENABLED) {
pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
}
}
- printk("%s ok\n", __func__);
+ EHCI_PRINT("%s ok\n", __func__);
return 0;
static int ehci_rk_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+
+ device_remove_file(dev, &dev_attr_ehci_power);
+ device_remove_file(dev, &dev_attr_debug_ehci);
+ device_remove_file(dev, &dev_attr_test_sq);
usb_put_hcd(hcd);
.resume = ehci_rk_pm_resume,
};
-static struct platform_driver ehci_rk_driver = {
+static struct platform_driver rk_ehci_driver = {
.probe = ehci_rk_probe,
.remove = ehci_rk_remove,
.driver = {
#endif
},
};
+
+static const struct ehci_driver_overrides rk_overrides __initdata = {
+ .extra_priv_size = sizeof(struct rk_ehci_hcd),
+};
+
+static int __init ehci_rk_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ ehci_init_driver(&rk_ehci_hc_driver, &rk_overrides);
+ return platform_driver_register(&rk_ehci_driver);
+}
+module_init(ehci_rk_init);
+
+static void __exit ehci_rk_cleanup(void)
+{
+ platform_driver_unregister(&rk_ehci_driver);
+}
+module_exit(ehci_rk_cleanup);
+MODULE_AUTHOR("Rockchip");
+MODULE_LICENSE("GPL v2");
+
if (hdmi_drv->irq)
disable_irq(hdmi_drv->irq);
mutex_unlock(&hdmi_drv->enable_mutex);
+ if (hdmi_drv->hotplug == HDMI_HPD_ACTIVED)
+ rk3036_hdmi_control_output(hdmi_drv, 0);
}
hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi shut down.\n");
}
struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
struct rk_hdmi_device,
driver);
-
- hdmi_writel(hdmi_dev, AV_MUTE,
- v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
+ if (enable) {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
+ v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
+ } else {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
+ v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
+ }
+ hdmi_writel(hdmi_dev, PACKET_SEND_AUTO, m_PACKET_GCP_EN);
}
static void rk3036_hdmi_sys_power(struct hdmi *hdmi_drv, bool enable)
hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
hdmi_writel(hdmi_dev, 0xce, 0x00);
hdmi_writel(hdmi_dev, 0xce, 0x01);
- rk3036_hdmi_av_mute(hdmi_drv, 1);
rk3036_hdmi_sys_power(hdmi_drv, true);
break;
case LOWER_PWR:
hdmi_dbg(hdmi_drv->dev,
"%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
__func__, hdmi_drv->pwr_mode, mode);
- rk3036_hdmi_av_mute(hdmi_drv, 0);
rk3036_hdmi_sys_power(hdmi_drv, false);
hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
vpara->output_color = VIDEO_OUTPUT_RGB444;*/
}
- if (hdmi_drv->pwr_mode == LOWER_PWR)
+/* if (hdmi_drv->pwr_mode == LOWER_PWR)
rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-
+*/
/* Disable video and audio output */
- hdmi_writel(hdmi_dev, AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AUDIO_MUTE | m_VIDEO_BLACK,
+ v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
/* Input video mode is SDR RGB24bit, Data enable signal from external */
hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
value = mode->vsync_len;
hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
#endif
-
if (vpara->output_mode == OUTPUT_HDMI) {
rk3036_hdmi_config_avi(hdmi_drv, vpara->vic,
vpara->output_color);
if (enable) {
if (hdmi_drv->pwr_mode == LOWER_PWR)
rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
- hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
- if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
- hdmi_writel(hdmi_dev, AV_MUTE,
- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
- }
+
rk3036_hdmi_sys_power(hdmi_drv, true);
rk3036_hdmi_sys_power(hdmi_drv, false);
delay100us();
hdmi_writel(hdmi_dev, 0xce, 0x00);
delay100us();
hdmi_writel(hdmi_dev, 0xce, 0x01);
+
+ hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
+ if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AUDIO_MUTE | m_VIDEO_BLACK,
+ v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
+ }
+ rk3036_hdmi_av_mute(hdmi_drv, 0);
} else {
- hdmi_writel(hdmi_dev, AV_MUTE,
- v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AUDIO_MUTE | m_VIDEO_BLACK,
+ v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+ rk3036_hdmi_av_mute(hdmi_drv, 1);
+ msleep(100);
+ rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
}
}
#define m_AVMUTE_ENABLE (1 << 6)
#define m_AUDIO_MUTE (1 << 1)
#define m_VIDEO_BLACK (1 << 0)
+#define v_AVMUTE_CLEAR(n) (n << 7)
+#define v_AVMUTE_ENABLE(n) (n << 6)
#define v_AUDIO_MUTE(n) (n << 1)
#define v_VIDEO_MUTE(n) (n << 0)
#define EDID_FIFO_OFFSET 0x4f
#define EDID_FIFO_ADDR 0x50
+
+#define PACKET_SEND_MANUAL 0x9c
+#define PACKET_SEND_AUTO 0x9d
+ #define m_PACKET_GCP_EN (1 << 7)
/* CONTROL_PACKET_BUF_INDEX */
#define CONTROL_PACKET_BUF_INDEX 0x9f
enum {
kobject_uevent_env(&hdmi->ddev->dev->kobj, KOBJ_REMOVE, envp);
#ifdef CONFIG_SWITCH
- if (audio_need)
+ if (audio_need ||
+ rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
switch_set_state(&(hdmi->switch_hdmi), 0);
#endif
rockchip_clear_system_status(SYS_STATUS_HDMI);
if (!hdmi->enable || hdmi->suspend) {
if (hdmi->hotplug != HDMI_HPD_REMOVED) {
hdmi->hotplug = HDMI_HPD_REMOVED;
+ hdmi->control_output(hdmi, HDMI_DISABLE);
hdmi_sys_remove(hdmi);
}
hdmi->state = HDMI_SLEEP;
default:
if (state > SYSTEM_CONFIG) {
state = SYSTEM_CONFIG;
+ hdmi->control_output(hdmi, HDMI_DISABLE);
+ msleep(2000);
} else {
if (hdmi->wait == 1) {
complete(&hdmi->complete);
hdmi->hotplug = hotplug;
} else if (hotplug == HDMI_HPD_REMOVED) {
hdmi_sys_sleep(hdmi);
- }else if (hotplug == HDMI_HPD_ACTIVED) {
+ } else if (hotplug == HDMI_HPD_ACTIVED) {
if (hdmi->uboot_logo) {
if (hdmi->insert)
hdmi->insert(hdmi);
hdmi->edid.base_audio_support,
hdmi->edid.sink_hdmi);
#ifdef CONFIG_SWITCH
- if (hdmi->edid.base_audio_support == 1 &&
- hdmi->edid.sink_hdmi == 1)
+ if ((hdmi->edid.base_audio_support == 1 &&
+ hdmi->edid.sink_hdmi == 1) ||
+ (rk_fb_get_display_policy() ==
+ DISPLAY_POLICY_BOX))
switch_set_state(&(hdmi->switch_hdmi),
1);
#endif
"wakeup from standby!\n");
lcdc_dev->standby = 0;
}
- lcdc_dev->atv_layer_cnt++;
- } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
- lcdc_dev->atv_layer_cnt--;
+ lcdc_dev->atv_layer_cnt |= (1 << win_id);
+ } else if ((lcdc_dev->atv_layer_cnt & (1 << win_id)) && (!open)) {
+ lcdc_dev->atv_layer_cnt &= ~(1 << win_id);
}
lcdc_dev->driver.win[win_id]->state = open;
if (!open) {
mask = m_WIN1_ALPHA_MODE |
m_ALPHA_MODE_SEL0 | m_ALPHA_MODE_SEL1;
- val = v_WIN1_ALPHA_MODE(1) |
- v_ALPHA_MODE_SEL0(1) | v_ALPHA_MODE_SEL1(0);
+ if (lcdc_dev->driver.overlay_mode == VOP_YUV_DOMAIN)
+ val = v_WIN0_ALPHA_MODE(1) |
+ v_ALPHA_MODE_SEL0(0) |
+ v_ALPHA_MODE_SEL1(0);
+ else
+ val = v_WIN1_ALPHA_MODE(1) |
+ v_ALPHA_MODE_SEL0(1) |
+ v_ALPHA_MODE_SEL1(0);
lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
/*this vop bg layer not support yuv domain overlay,so bg val
have to set 0x800a80 equeal to 0x000000 at rgb domian,after
return 0;
}
-static int rk312x_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
+static int rk312x_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv,
+ int reset_rate)
{
#ifdef CONFIG_RK_FPGA
return 0;
container_of(dev_drv, struct lcdc_device, driver);
struct rk_screen *screen = dev_drv->cur_screen;
- ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+ if (reset_rate)
+ ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
if (ret)
dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
lcdc_dev->pixclock =
lcdc_cfg_done(lcdc_dev);
while(lcdc_readl(lcdc_dev, SYS_CTRL) & (m_WIN0_EN | m_WIN1_EN));
}*/
- if ((dev_drv->ops->open_bcsh) && (dev_drv->output_color == COLOR_YCBCR))
- dev_drv->ops->open_bcsh(dev_drv, 1);
+ if ((dev_drv->ops->open_bcsh) && (dev_drv->output_color == COLOR_YCBCR)) {
+ if (support_uboot_display())
+ dev_drv->bcsh_init_status = 1;
+ else
+ dev_drv->ops->open_bcsh(dev_drv, 1);
+ }
lcdc_dev->pre_init = true;
return 0;
static void rk312x_lcdc_select_bcsh(struct rk_lcdc_driver *dev_drv,
struct lcdc_device *lcdc_dev)
{
+ u32 bcsh_ctrl;
if (dev_drv->overlay_mode == VOP_YUV_DOMAIN) {
if (dev_drv->output_color == COLOR_YCBCR)/* bypass */
lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
v_BCSH_Y2R_CSC_MODE(VOP_Y2R_CSC_MPEG) |
v_BCSH_R2Y_EN(0));
} else { /* overlay_mode=VOP_RGB_DOMAIN */
- if (dev_drv->output_color == COLOR_RGB) /* bypass */
- lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
- m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
- v_BCSH_R2Y_EN(1) | v_BCSH_Y2R_EN(1));
- else /* RGB2YUV */
+ if (dev_drv->output_color == COLOR_RGB) {
+ /* bypass */
+ bcsh_ctrl = lcdc_readl(lcdc_dev, BCSH_CTRL);
+ if ((bcsh_ctrl&m_BCSH_EN) == 1)/*bcsh enabled*/
+ lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
+ m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
+ v_BCSH_R2Y_EN(1) | v_BCSH_Y2R_EN(1));
+ else/*bcsh disabled*/
+ lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
+ m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
+ v_BCSH_R2Y_EN(0) | v_BCSH_Y2R_EN(0));
+ } else /* RGB2YUV */
lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
m_BCSH_R2Y_EN |
m_BCSH_R2Y_CSC_MODE | m_BCSH_Y2R_EN,
break;
}
if (lcdc_dev->soc_type == VOP_RK312X) {
- switch (screen->face) {
+ switch (dev_drv->screen0->face) {
case OUT_P565:
face = OUT_P565;
mask = m_DITHER_DOWN_EN |
}
}
spin_unlock(&lcdc_dev->reg_lock);
- rk312x_lcdc_set_dclk(dev_drv);
+ rk312x_lcdc_set_dclk(dev_drv, 1);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY, v_LCDC_STANDBY(0));
lcdc_cfg_done(lcdc_dev);
if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
/*if (dev_drv->iommu_enabled)
rk312x_lcdc_mmu_en(dev_drv);*/
if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
- /*rk312x_lcdc_set_dclk(dev_drv);*/
+ rk312x_lcdc_set_dclk(dev_drv, 0);
rk312x_lcdc_enable_irq(dev_drv);
} else {
rk312x_load_screen(dev_drv, 1);
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
u32 mask, val;
-
+ if (dev_drv->bcsh_init_status && open) {
+ dev_drv->bcsh_init_status = 0;
+ return 0;
+ }
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
rk312x_lcdc_select_bcsh(dev_drv, lcdc_dev);
#include <linux/rk_fb.h>
#include <linux/linux_logo.h>
#include <linux/dma-mapping.h>
+#include <linux/regulator/consumer.h>
#if defined(CONFIG_RK_HDMI)
#include "hdmi/rk_hdmi.h"
return uboot_logo_on;
}
+int rk_fb_get_display_policy(void)
+{
+ struct rk_fb *rk_fb;
+
+ if (fb_pdev) {
+ rk_fb = platform_get_drvdata(fb_pdev);
+ return rk_fb->disp_policy;
+ } else {
+ return DISPLAY_POLICY_SDK;
+ }
+}
+
int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
{
switch (type) {
} else {
pwr_ctr->pwr_ctr.type = REGULATOR;
-
+ pwr_ctr->pwr_ctr.rgl_name = NULL;
+ ret = of_property_read_string(child, "rockchip,regulator_name",
+ &(pwr_ctr->pwr_ctr.rgl_name));
+ if (ret || IS_ERR_OR_NULL(pwr_ctr->pwr_ctr.rgl_name))
+ dev_err(dev_drv->dev, "get regulator name failed!\n");
+ if (!of_property_read_u32(child, "rockchip,regulator_voltage", &val))
+ pwr_ctr->pwr_ctr.volt = val;
+ else
+ pwr_ctr->pwr_ctr.volt = 0;
}
};
- of_property_read_u32(child, "rockchip,delay", &val);
- pwr_ctr->pwr_ctr.delay = val;
+
+ if (!of_property_read_u32(child, "rockchip,delay", &val))
+ pwr_ctr->pwr_ctr.delay = val;
+ else
+ pwr_ctr->pwr_ctr.delay = 0;
list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
}
struct list_head *pos;
struct rk_disp_pwr_ctr_list *pwr_ctr_list;
struct pwr_ctr *pwr_ctr;
+ struct regulator *regulator_lcd = NULL;
+ int count = 10;
+
if (list_empty(&dev_drv->pwrlist_head))
return 0;
list_for_each(pos, &dev_drv->pwrlist_head) {
if (pwr_ctr->type == GPIO) {
gpio_direction_output(pwr_ctr->gpio, pwr_ctr->atv_val);
mdelay(pwr_ctr->delay);
+ } else if (pwr_ctr->type == REGULATOR) {
+ if (pwr_ctr->rgl_name)
+ regulator_lcd = regulator_get(NULL, pwr_ctr->rgl_name);
+ if (regulator_lcd == NULL) {
+ dev_err(dev_drv->dev,
+ "%s: regulator get failed,regulator name:%s\n",
+ __func__, pwr_ctr->rgl_name);
+ continue;
+ }
+ regulator_set_voltage(regulator_lcd, pwr_ctr->volt, pwr_ctr->volt);
+ while (!regulator_is_enabled(regulator_lcd)) {
+ if (regulator_enable(regulator_lcd) == 0 || count == 0)
+ break;
+ else
+ dev_err(dev_drv->dev,
+ "regulator_enable failed,count=%d\n",
+ count);
+ count--;
+ }
+ regulator_put(regulator_lcd);
+ msleep(pwr_ctr->delay);
}
}
struct list_head *pos;
struct rk_disp_pwr_ctr_list *pwr_ctr_list;
struct pwr_ctr *pwr_ctr;
+ struct regulator *regulator_lcd = NULL;
+ int count = 10;
+
if (list_empty(&dev_drv->pwrlist_head))
return 0;
list_for_each(pos, &dev_drv->pwrlist_head) {
pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
list);
pwr_ctr = &pwr_ctr_list->pwr_ctr;
- if (pwr_ctr->type == GPIO)
+ if (pwr_ctr->type == GPIO) {
gpio_set_value(pwr_ctr->gpio, !pwr_ctr->atv_val);
+ } else if (pwr_ctr->type == REGULATOR) {
+ if (pwr_ctr->rgl_name)
+ regulator_lcd = regulator_get(NULL, pwr_ctr->rgl_name);
+ if (regulator_lcd == NULL) {
+ dev_err(dev_drv->dev,
+ "%s: regulator get failed,regulator name:%s\n",
+ __func__, pwr_ctr->rgl_name);
+ continue;
+ }
+ while (regulator_is_enabled(regulator_lcd) > 0) {
+ if (regulator_disable(regulator_lcd) == 0 || count == 0)
+ break;
+ else
+ dev_err(dev_drv->dev,
+ "regulator_disable failed,count=%d\n",
+ count);
+ count--;
+ }
+ regulator_put(regulator_lcd);
+ }
}
return 0;
}
reg_win_data->reg_area_data[i].ysize *
cur_screen->mode.yres /
primary_screen.mode.yres;
+
+ /* recalc display size if set hdmi scaler when at ONE_DUAL mode */
+ if (inf->disp_mode == ONE_DUAL && hdmi_switch_complete) {
+ if (cur_screen->xsize > 0 &&
+ cur_screen->xsize <= cur_screen->mode.xres) {
+ win->area[i].xpos =
+ ((cur_screen->mode.xres - cur_screen->xsize) >> 1) +
+ cur_screen->xsize * win->area[i].xpos / cur_screen->mode.xres;
+ win->area[i].xsize =
+ win->area[i].xsize * cur_screen->xsize / cur_screen->mode.xres;
+ }
+ if (cur_screen->ysize > 0 && cur_screen->ysize <= cur_screen->mode.yres) {
+ win->area[i].ypos =
+ ((cur_screen->mode.yres - cur_screen->ysize) >> 1) +
+ cur_screen->ysize * win->area[i].ypos / cur_screen->mode.yres;
+ win->area[i].ysize =
+ win->area[i].ysize * cur_screen->ysize / cur_screen->mode.yres;
+ }
+ }
}
win->area[i].xact =
reg_win_data->reg_area_data[i].xact;
win_data = rk_fb_get_win_data(regs, i);
if (win_data) {
if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
- win_data->data_format == YUV420)
+ (win_data->data_format == YUV420 ||
+ win_data->data_format == YUV420_A))
continue;
rk_fb_update_win(dev_drv, win, win_data);
win->state = 1;
timeout = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
ktime_compare(dev_drv->vsync_info.timestamp, timestamp) > 0,
msecs_to_jiffies(25));
+ if ((rk_fb->disp_mode == DUAL) &&
+ (hdmi_get_hotplug() == HDMI_HPD_ACTIVED) &&
+ hdmi_switch_complete) {
+ /*
+ * If dual output, we need make sure the extend display
+ * cfg take effect before release fence.
+ */
+ ext_dev_drv = rk_get_extend_lcdc_drv();
+ timeout = wait_event_interruptible_timeout(ext_dev_drv->vsync_info.wait,
+ ktime_compare(ext_dev_drv->vsync_info.timestamp, timestamp) > 0,
+ msecs_to_jiffies(25));
+ }
+
dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
wait_for_vsync = false;
for (i = 0; i < dev_drv->lcdc_win_num; i++) {
if (dev_drv->win[i]->state == 1) {
if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
(dev_drv->win[i]->format == YUV420 ||
+ dev_drv->win[i]->format == YUV420_A ||
!strcmp(dev_drv->win[i]->name, "hwc"))) {
continue;
} else {
dev_drv->win[i]->area[0].y_offset;
u32 reg_start = dsp_addr[i];
- if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
- new_start==0x0)
+ if ((rk_fb->disp_policy ==
+ DISPLAY_POLICY_BOX) &&
+ (new_start == 0x0 ||
+ dev_drv->suspend_flag))
continue;
if (unlikely(new_start != reg_start)) {
wait_for_vsync = true;
}
}
}
+
+ /* record buffer information for rk_fb_disp_scale to prevent fence timeout
+ * because rk_fb_disp_scale will call function info->fbops->fb_set_par(info);
+ */
+ info->var.yoffset = yoffset;
+ info->var.xoffset = xoffset;
return 0;
}
(win->format == ABGR888)) ? 1 : 0;
win->g_alpha_val = 0;
+ if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
+ (win->format == YUV420 || win->format == YUV420_A))
+ win->state = 1;
if (rk_fb->disp_mode == DUAL) {
if (extend_win->state && hdmi_switch_complete) {
if (info != extend_info) {
struct list_head *pos;
struct property *prop;
enum of_gpio_flags flags;
- u32 value, i, debug, gpio, ret, cmds[25], length;
+ u32 value, i, debug, gpio, ret, length;
+ u32 cmds[sizeof(dcs_cmd->dcs_cmd.cmds) / sizeof(u32)];
memset(screen, 0, sizeof(*screen));
return -EINVAL;
}
+ if (length > sizeof(dcs_cmd->dcs_cmd.cmds)) {
+ /* the length can not longer than the cmds arrary in struct dcs_cmds */
+ MIPI_SCREEN_DBG("error: the dcs cmd length is %d, but the max length supported is %d\n",
+ length / sizeof(u32), sizeof(dcs_cmd->dcs_cmd.cmds) / sizeof(32));
+ }
MIPI_SCREEN_DBG("\n childnode->name =%s:length=%d\n", childnode->name, (length / sizeof(u32)));
ret = of_property_read_u32_array(childnode, "rockchip,cmd", cmds, (length / sizeof(u32)));
return ret;
} else {
dcs_cmd->dcs_cmd.cmd_len = length / sizeof(u32);
- for (i = 0; i < (length / sizeof(u32)); i++) {
+ for (i = 0; (i < (length / sizeof(u32))) && (i < (sizeof(dcs_cmd->dcs_cmd.cmds) / sizeof(u32))); i++) {
+ /* avoid the array out of range */
MIPI_SCREEN_DBG("cmd[%d]=%02x£¬", i+1, cmds[i]);
dcs_cmd->dcs_cmd.cmds[i] = cmds[i];
}
val |= (data & bits) << offset;
rk32_dsi_write_reg(dsi, reg_addr, &val);
- if (data > bits) {
+ if(data > ((1 << (bits+1)) - 1)) {
MIPI_TRACE("%s error reg_addr:0x%04x, offset:%d, bits:0x%04x, value:0x%04x\n",
__func__, reg_addr, offset, bits, data);
}
rk32_dsi_set_bits(dsi, 1000, lprx_to_cnt);
rk32_dsi_set_bits(dsi, 100, phy_stop_wait_time);
- /*
- rk32_dsi_set_bits(dsi, 0, outvact_lpcmd_time);
- rk32_dsi_set_bits(dsi, 0, invact_lpcmd_time);
- */
+ /* enable send command in low power mode */
+ rk32_dsi_set_bits(dsi, 4, outvact_lpcmd_time);
+ rk32_dsi_set_bits(dsi, 4, invact_lpcmd_time);
+ rk32_dsi_set_bits(dsi, 1, lp_cmd_en);
+
rk32_dsi_set_bits(dsi, 20, phy_hs2lp_time);
rk32_dsi_set_bits(dsi, 16, phy_lp2hs_time);
/*
/* rk32_dsi_set_bits(dsi, 1, frame_bta_ack_en); */
rk32_dsi_set_bits(dsi, 1, phy_enableclk);
rk32_dsi_set_bits(dsi, 0, phy_tx_triggers);
+
+ /* enable non-continued function */
+ rk32_dsi_set_bits(dsi, 1, auto_clklane_ctrl);
/*
rk32_dsi_set_bits(dsi, 1, phy_txexitulpslan);
rk32_dsi_set_bits(dsi, 1, phy_txexitulpsclk);
data = (dsi->vid << 6) | type;
data |= (liTmp & 0xffff) << 8;
break;
- case DTYPE_GEN_SWRITE_2P:
+ case DTYPE_GEN_SWRITE_2P: /* one command and one parameter */
rk32_dsi_set_bits(dsi, regs[0], gen_sw_2p_tx);
+ if (liTmp <= 2) {
+ /* It is used for normal Generic Short WRITE Packet with 2 parameters. */
+ data = type;
+ data |= regs[2] << 8; /* dcs command */
+ data |= regs[3] << 16; /* parameter of command */
+ break;
+ }
+
+ /* The below is used for Generic Short WRITE Packet with 2 parameters
+ * that more than 2 parameters. Though it is illegal dcs command, we can't
+ * make sure the users do not send that command.
+ */
for (i = 0; i < liTmp; i++) {
regs[i] = regs[i+2];
}
data = type;
data |= (liTmp & 0xffff) << 8;
break;
- case DTYPE_GEN_SWRITE_1P:
+ case DTYPE_GEN_SWRITE_1P: /* one command without parameter */
rk32_dsi_set_bits(dsi, regs[0], gen_sw_1p_tx);
data = type;
data |= regs[2] << 8;
- data |= regs[3] << 16;
break;
- case DTYPE_GEN_SWRITE_0P:
+ case DTYPE_GEN_SWRITE_0P: /* nop packet without command and parameter */
rk32_dsi_set_bits(dsi, regs[0], gen_sw_0p_tx);
data = type;
- data |= regs[2] << 8;
break;
default:
printk("0x%x:this type not suppport!\n", type);
return count;
}
-int reg_proc_read(struct file *file, char __user *buff, size_t count,
- loff_t *offp)
+int reg_proc_read(struct seq_file *s, void *v)
{
int i = 0;
u32 val = 0;
-
+ struct dsi *dsi = s->private;
+
for (i = VERSION; i < (VERSION + (0xdc << 16)); i += 4<<16) {
- val = rk32_dsi_get_bits(dsi0, i);
- MIPI_TRACE("%04x: %08x\n", i>>16, val);
- msleep(1);
+ val = rk32_dsi_get_bits(dsi, i);
+ seq_printf(s, "%04x: %08x\n", i>>16, val);
}
-
- MIPI_TRACE("\n");
- return -1;
+ return 0;
}
-
-int reg_proc_open(struct inode *inode, struct file *file)
+static int reg_proc_open(struct inode *inode, struct file *file)
{
- return 0;
+ struct dsi *dsi = inode->i_private;
+
+ return single_open(file, reg_proc_read, dsi);
}
int reg_proc_close(struct inode *inode, struct file *file)
.open = reg_proc_open,
.release = reg_proc_close,
.write = reg_proc_write,
- .read = reg_proc_read,
+ .read = seq_read,
};
int reg_proc_write1(struct file *file, const char __user *buff, size_t count, loff_t *offp)
return count;
}
-int reg_proc_read1(struct file *file, char __user *buff, size_t count,
- loff_t *offp)
-{
- int i = 0;
- u32 val = 0;
-
- for (i = VERSION; i < (VERSION + (0xdc<<16)); i += 4<<16) {
- val = rk32_dsi_get_bits(dsi1, i);
- MIPI_TRACE("%04x: %08x\n", i>>16, val);
- msleep(1);
- }
-
- MIPI_TRACE("\n");
- return -1;
-}
-
-int reg_proc_open1(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
int reg_proc_close1(struct inode *inode, struct file *file)
{
return 0;
struct file_operations reg_proc_fops1 = {
.owner = THIS_MODULE,
- .open = reg_proc_open1,
+ .open = reg_proc_open,
.release = reg_proc_close1,
.write = reg_proc_write1,
- .read = reg_proc_read1,
+ .read = seq_read,
};
#endif
#if 0/* def CONFIG_MIPI_DSI_LINUX */
rk_display_device_enable(rk3036_tve->ddev);
fb_register_client(&tve_fb_notifier);
+ cvbsformat = -1;
dev_info(&pdev->dev, "%s tv encoder probe ok\n", match->compatible);
return 0;
}
unsigned int prev_blksz;
unsigned char timing;
struct workqueue_struct *card_workqueue;
- struct delayed_work resume_rescan;
/* DMA interface members*/
int use_dma;
int is_dc_charge;
int is_usb_charge;
+ int auto_calibration;
struct iio_channel *chan;
+ struct iio_channel *ref_voltage_chan;
};
#endif
int is_rst;
int gpio;
int atv_val;
- char rgl_name[32];
+ const char *rgl_name;
int volt;
int delay;
};
struct rk_lcdc_bcsh bcsh;
int *hwc_lut;
int uboot_logo;
+ int bcsh_init_status;
};
struct rk_fb_par {
extern struct device *rk_fb_get_sysmmu_device_by_compatible(const char *compt);
extern void rk_fb_platform_set_sysmmu(struct device *sysmmu,
struct device *dev);
+int rk_fb_get_display_policy(void);
#endif
int rockchip_set_system_status(unsigned long status);
int rockchip_clear_system_status(unsigned long status);
unsigned long rockchip_get_system_status(void);
+u32 pvtm_get_value(u32 ch, u32 time_us);
#define INVALID_TEMP INT_MAX
#if IS_ENABLED(CONFIG_SENSORS_ROCKCHIP_TSADC)
#include <linux/device.h>
#include <linux/clk-provider.h>
+#define ARM_DVFS_CH 0
+#define GPU_DVFS_CH 1
+#define LOG_DVFS_CH 2
+
struct dvfs_node;
typedef int (*dvfs_set_rate_callback)(struct dvfs_node *clk_dvfs_node, unsigned long rate);
typedef int (*clk_set_rate_callback)(struct clk *clk, unsigned long rate);
unsigned int regu_mode;
};
+struct pvtm_info {
+ const char *compatible;
+ struct cpufreq_frequency_table *pvtm_table;
+ int channel;
+ int process_version;
+ int scan_rate_hz;
+ int sample_time_us;
+ int volt_step_uv;
+ int delta_pvtm_by_volt;
+ int delta_pvtm_by_temp;
+ int volt_margin_uv;
+ int min_volt_uv;
+ int max_volt_uv;
+};
+
+struct lkg_adjust_volt_table {
+ int lkg;
+ int dlt_volt;
+};
+
+struct lkg_info {
+ int def_table_lkg;
+ int min_adjust_freq;
+ struct lkg_adjust_volt_table *table;
+};
+
/**
* struct dvfs_node: To Store All dvfs clocks' info
* @name: Dvfs clock's Name
int set_volt; //MV
int enable_count;
int freq_limit_en; //sign if use limit frequency
+ int support_pvtm;
unsigned int min_rate; //limit min frequency
unsigned int max_rate; //limit max frequency
unsigned long last_set_rate;
+ unsigned int channel;
unsigned int temp_channel;
unsigned long temp_limit_rate;
struct clk *clk;
struct list_head node;
struct notifier_block *dvfs_nb;
struct cpufreq_frequency_table *dvfs_table;
+ struct cpufreq_frequency_table *pvtm_table;
struct cpufreq_frequency_table *per_temp_limit_table;
struct cpufreq_frequency_table *nor_temp_limit_table;
struct cpufreq_frequency_table *virt_temp_limit_table[4];
struct cpufreq_frequency_table *regu_mode_table;
int regu_mode_en;
unsigned int regu_mode;
+ struct pvtm_info *pvtm_info;
+ int lkg_adjust_volt_en;
+ struct lkg_info lkg_info;
};
1) support isp iommu
*v0.9.0:
1) add dev_name in struct camsys_devio_name_s;
+*v0.a.0:
+ 1) support external flash IC
*/
-#define CAMSYS_HEAD_VERSION KERNEL_VERSION(0,9,0)
+#define CAMSYS_HEAD_VERSION KERNEL_VERSION(0,0xa,0)
#define CAMSYS_MARVIN_DEVNAME "camsys_marvin"
#define CAMSYS_CIF0_DEVNAME "camsys_cif0"
} camsys_sysctrl_t;
typedef struct camsys_flash_info_s {
- camsys_gpio_info_t fl;
+ unsigned char fl_drv_name[CAMSYS_NAME_LEN];
+ camsys_gpio_info_t fl; //fl_trig
+ camsys_gpio_info_t fl_en;
} camsys_flash_info_t;
typedef struct camsys_mipiphy_s {
params_channels(p)) / 8;
}
+#define HW_PARAMS_FLAG_LPCM 0
+#define HW_PARAMS_FLAG_NLPCM 1
+
#endif /* __SOUND_PCM_PARAMS_H */
detach_vmas_to_be_unmapped(mm, vma, prev, end);
unmap_region(mm, vma, prev, start, end);
+#ifdef CONFIG_ARCH_ROCKCHIP
+ {
+ extern int ion_munmap(void *dmabuf, struct vm_area_struct *vma);
+ extern int dma_buf_is_dma_buf(struct file *file);
+ if (vma->vm_file && dma_buf_is_dma_buf(vma->vm_file)) {
+ ion_munmap(vma->vm_file->private_data, vma);
+ }
+ }
+#endif
+
/* Fix up all other VM information */
remove_vma_list(mm, vma);
.rates = (SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_96000),
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE),
rk312x_codec_power_up(RK312x_CODEC_PLAYBACK);
snd_soc_write(rk312x_priv->codec, 0xb4, rk312x_priv->spk_volume);
snd_soc_write(rk312x_priv->codec, 0xb8, rk312x_priv->spk_volume);
+ msleep(rk312x_priv->spk_mute_delay);
rk312x_codec_ctl_gpio(CODEC_SET_SPK, rk312x_priv->spk_active_level);
}
} else {
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
- SNDRV_PCM_RATE_96000)
+ SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_192000)
#define RK312x_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
SNDRV_PCM_RATE_16000 | \
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
+ int div_bclk,div_mclk;
int ret;
DBG("Enter::%s----%d\n", __func__, __LINE__);
case 24000:
case 32000:
case 48000:
+ case 96000:
pll_out = 12288000;
break;
case 11025:
case 22050:
case 44100:
+ case 88200:
pll_out = 11289600;
break;
+ case 176400:
+ pll_out = 11289600*2;
+ break;
+ case 192000:
+ pll_out = 12288000*2;
+ break;
default:
pr_err("Enter:%s, %d, Error rate=%d\n",
__func__, __LINE__, params_rate(params));
__func__, __LINE__,
params_rate(params));
+ div_bclk = 63;
+ div_mclk = pll_out/(params_rate(params)*(div_bclk+1))-1;
+
snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,
- (pll_out / 4) / params_rate(params) - 1);
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
+ snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk);
+ snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
- DBG("Enter:%s, %d, pll_out / 4 / params_rate(params) = %d\n",
- __func__, __LINE__, (pll_out / 4) / params_rate(params));
+ DBG("Enter:%s, %d, div_bclk: %d, div_mclk: %d\n",
+ __func__, __LINE__, div_bclk, div_mclk);
return 0;
}
.channels_max = 8,
.buffer_bytes_max = 128*1024,
.period_bytes_min = 64,
- .period_bytes_max = 2048*4,
+ .period_bytes_max = 32*1024,//2048*4,///PAGE_SIZE*2,
.periods_min = 3,
.periods_max = 128,
.fifo_size = 16,
.pcm_hardware = &rockchip_pcm_hardware,
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
.compat_filter_fn = NULL,
- .prealloc_buffer_size = PAGE_SIZE * 8,
+ .prealloc_buffer_size = PAGE_SIZE * 32,
};
int rockchip_pcm_platform_register(struct device *dev)
#include "rk_pcm.h"
#undef DEBUG_SPDIF
-#define DEBUG_SPDIF 1
+#define DEBUG_SPDIF 0
#if DEBUG_SPDIF
#define RK_SPDIF_DBG(x...) pr_info("rk_spdif:"x)
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
#include <linux/module.h>
+#ifdef CONFIG_SWITCH
#include <linux/switch.h>
+#endif
#include <sound/control.h>
#include <sound/core.h>
static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
static struct usb_driver usb_audio_driver;
#ifdef CONFIG_SND_RK_SOC
-#define USB_AUDIO_CARD_NUM 2
+#define USB_AUDIO_CARD_NUM 3
struct switch_dev *usb_audio_sdev;
#endif
+#ifdef CONFIG_SWITCH
+//usb audio card will begin from RBASE_USB_AUDIO_IDX.
+#define RBASE_USB_AUDIO_IDX (3)
+#define NO_USBAUDIO_PLAYBACK (-1)
+#define NO_USBAUDIO_CAPTURE (-1)
+
+struct usb_audio_switch {
+ int playback_switch_cur_state;
+ int capture_switch_cur_state;
+ struct switch_dev sUsbaudio_Playback;
+ struct switch_dev sUsbaudio_Capture;
+};
+
+// state: card*10 + device
+static struct usb_audio_switch sUsbaudio_Switch = {
+ .playback_switch_cur_state = NO_USBAUDIO_PLAYBACK,
+ .capture_switch_cur_state = NO_USBAUDIO_CAPTURE,
+ .sUsbaudio_Playback = {
+ .name = "usb_audio_playback",
+ .state = NO_USBAUDIO_PLAYBACK, //this means no usb audio playback available
+ },
+
+ .sUsbaudio_Capture = {
+ .name = "usb_audio_capture",
+ .state = NO_USBAUDIO_CAPTURE, //this means no usb audio capture available
+ },
+};
+#endif
+
/*
* disconnect streams
* called from snd_usb_audio_disconnect()
return 0;
}
+#ifdef CONFIG_SWITCH
+static int usb_audio_card_switch_state_update(struct snd_card *card, bool force){
+ struct snd_device *dev;
+ struct snd_pcm *pcm;
+ struct snd_pcm_str *pstr;
+
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
+ //we use the latest devices
+ list_for_each_entry(dev, &card->devices, list) {
+ if (dev->type == SNDRV_DEV_PCM && dev->state == SNDRV_DEV_REGISTERED) {
+ pcm = (struct snd_pcm*)dev->device_data;
+ if (NULL != pcm) {
+ //playback available?
+ pstr = &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
+ snd_printdd(KERN_INFO "playback substream_count: 0x%x\n", pstr->substream_count);
+ if (pstr->substream_count > 0) {
+ sUsbaudio_Switch.playback_switch_cur_state = card->number * 10;
+ }
+ //capture available?
+ pstr = &pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
+ snd_printdd(KERN_INFO "capture substream_count: 0x%x\n", pstr->substream_count);
+ if (pstr->substream_count > 0) {
+ sUsbaudio_Switch.capture_switch_cur_state = card->number * 10;
+ }
+ }
+ }
+ }
+ if (force) {
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Playback, sUsbaudio_Switch.playback_switch_cur_state);
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Capture, sUsbaudio_Switch.capture_switch_cur_state);
+ }
+ return 0;
+
+}
+
+static void usb_audio_switch_state_update_all(void)
+{
+ int index = 0;
+ struct snd_card *card;
+
+ sUsbaudio_Switch.playback_switch_cur_state = NO_USBAUDIO_PLAYBACK;
+ sUsbaudio_Switch.capture_switch_cur_state = NO_USBAUDIO_CAPTURE;
+
+ for (index = 0; index < SNDRV_CARDS; ++index) {
+ if (NULL != usb_chip[index]) {
+ card = usb_chip[index]->card;
+ usb_audio_card_switch_state_update(card, false);
+ }
+ }
+
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Playback,
+ sUsbaudio_Switch.playback_switch_cur_state);
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Capture,
+ sUsbaudio_Switch.capture_switch_cur_state);
+}
+#endif
+
+
/*
* probe the active usb device
*
/* it's a fresh one.
* now look for an empty slot and create a new card instance
*/
+ // use RBASE_USB_AUDIO_IDX instead of zero, modify by zxg.
for (i = 0; i < SNDRV_CARDS; i++)
if (enable[i] && ! usb_chip[i] &&
(vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
if (snd_card_register(chip->card) < 0) {
goto __error;
}
-
+#ifdef CONFIG_SWITCH
+ if (usb_audio_card_switch_state_update(chip->card, true) < 0) {
+ printk(KERN_ERR "usb_audio_card_switch_state_update failed!!!\n");
+ goto __error;
+ }
+#endif
usb_chip[chip->index] = chip;
chip->num_interfaces++;
chip->probing = 0;
} else {
mutex_unlock(®ister_mutex);
}
+#ifdef CONFIG_SWITCH
+ usb_audio_switch_state_update_all();
+#endif
}
/*
static int __init snd_usb_audio_init(void)
{
+ int ret;
+#ifdef CONFIG_SWITCH
+ int i;
+ ret = switch_dev_register(&sUsbaudio_Switch.sUsbaudio_Playback);
+ if (ret)
+ goto err;
+ ret = switch_dev_register(&sUsbaudio_Switch.sUsbaudio_Capture);
+ if (ret)
+ goto err_drv;
+
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Playback, NO_USBAUDIO_PLAYBACK);
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Capture, NO_USBAUDIO_CAPTURE);
+#endif
+
if (nrpacks < 1 || nrpacks > MAX_PACKS) {
printk(KERN_WARNING "invalid nrpacks value.\n");
return -EINVAL;
}
-
#ifdef CONFIG_SND_RK_SOC
usb_audio_sdev = kzalloc(sizeof(usb_audio_sdev), GFP_KERNEL);
usb_audio_sdev->name = "usb_audio";
}
#endif
+ //re initial array index for rebasing usb audio cards create, modify by zxg.
+ for(i=0; i<SNDRV_CARDS; ++i){
+ index[i] = i;
+ }
+
return usb_register(&usb_audio_driver);
+
+err_drv:
+#ifdef CONFIG_SWITCH
+ switch_dev_unregister(&sUsbaudio_Switch.sUsbaudio_Playback);
+#endif
+err:
+ return ret;
+
}
static void __exit snd_usb_audio_cleanup(void)
#ifdef CONFIG_SND_RK_SOC
kfree(usb_audio_sdev);
#endif
+ switch_dev_unregister(&sUsbaudio_Switch.sUsbaudio_Capture);
+ switch_dev_unregister(&sUsbaudio_Switch.sUsbaudio_Playback);
}
-module_init(snd_usb_audio_init);
+/*module_init(snd_usb_audio_init);*/
+/* use late initcall_sync instead of module_init,
+ * make sure that usbaudio probe after board codec.
+ * added by zxg@rock-chips.com
+ */
+late_initcall_sync(snd_usb_audio_init);
module_exit(snd_usb_audio_cleanup);