armbian-build/patch/kernel/archive/spacemit-6.1/057-update-to-v1.0.3.patch

3541 lines
113 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Sat, 22 Jun 2024 08:49:36 -0400
Subject: update to v1.0.3
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
Makefile | 6 +-
drivers/clk/spacemit/ccu-spacemit-k1x.c | 4 +-
drivers/gpu/drm/img-rogue/rgxtimecorr.c | 2 +-
drivers/gpu/drm/spacemit/Kconfig | 16 +-
drivers/gpu/drm/spacemit/Makefile | 2 +
drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c | 6 +-
drivers/gpu/drm/spacemit/dpu/dpu_saturn.c | 10 +-
drivers/gpu/drm/spacemit/lt8911exb.c | 236 +--
drivers/gpu/drm/spacemit/lt9711.c | 406 ++++
drivers/gpu/drm/spacemit/spacemit_dsi.c | 8 +-
drivers/gpu/drm/spacemit/spacemit_hdmi.c | 39 +-
drivers/pci/controller/dwc/pcie-k1x.c | 57 +-
drivers/regulator/spacemit-regulator.c | 27 +-
drivers/remoteproc/k1x-rproc.c | 9 +-
drivers/soc/spacemit/jpu/jpu.c | 4 +-
drivers/soc/spacemit/pm_domain/k1x-pm_domain.c | 3 +-
drivers/spi/spi-k1x-qspi.c | 5 +-
drivers/target/target_core_configfs.c | 20 +
drivers/target/target_core_spc.c | 920 ++++++++++
drivers/tty/serial/pxa_k1x.c | 4 +-
drivers/usb/gadget/function/f_tcm.c | 26 +-
drivers/usb/gadget/function/tcm.h | 1 +
include/linux/mfd/spacemit/spacemit_pmic.h | 1 +
include/linux/mfd/spacemit/spm8821.h | 5 +-
include/scsi/scsi_proto.h | 10 +
include/target/target_core_base.h | 18 +
init/version-timestamp.c | 2 +-
sound/soc/codecs/es8316.c | 28 +
sound/soc/codecs/es8326.c | 116 +-
sound/soc/spacemit/spacemit-snd-card.c | 55 +
sound/soc/spacemit/spacemit-snd-i2s.c | 41 +-
sound/soc/spacemit/spacemit-snd-pcm-dma.c | 12 +-
sound/soc/spacemit/spacemit-snd-sspa.c | 2 +-
33 files changed, 1848 insertions(+), 253 deletions(-)
diff --git a/Makefile b/Makefile
index 111111111111..222222222222 100644
--- a/Makefile
+++ b/Makefile
@@ -377,8 +377,9 @@ include $(srctree)/scripts/Kbuild.include
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
+KERNELGITVER = $(shell git rev-parse --short HEAD)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
-export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
+export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION KERNELGITVER
include $(srctree)/scripts/subarch.include
@@ -1332,7 +1333,8 @@ define filechk_version.h
((c) > 255 ? 255 : (c)))'; \
echo \#define LINUX_VERSION_MAJOR $(VERSION); \
echo \#define LINUX_VERSION_PATCHLEVEL $(PATCHLEVEL); \
- echo \#define LINUX_VERSION_SUBLEVEL $(SUBLEVEL)
+ echo \#define LINUX_VERSION_SUBLEVEL $(SUBLEVEL); \
+ echo \#define LINUX_VERSION_COMMITID \"$(KERNELGITVER)\"
endef
$(version_h): PATCHLEVEL := $(or $(PATCHLEVEL), 0)
diff --git a/drivers/clk/spacemit/ccu-spacemit-k1x.c b/drivers/clk/spacemit/ccu-spacemit-k1x.c
index 111111111111..222222222222 100644
--- a/drivers/clk/spacemit/ccu-spacemit-k1x.c
+++ b/drivers/clk/spacemit/ccu-spacemit-k1x.c
@@ -643,10 +643,10 @@ static SPACEMIT_CCU_GATE_NO_PARENT(onewire_clk, "onewire_clk", NULL,
BASE_TYPE_APBC, APBC_ONEWIRE_CLK_RST,
0x3, 0x3, 0x0, 0);
-static SPACEMIT_CCU_GATE_FACTOR(i2s_sysclk, "i2s_sysclk", "pll1_d16_153p6",
+static SPACEMIT_CCU_GATE_FACTOR(i2s_sysclk, "i2s_sysclk", "pll1_d8_307p2",
BASE_TYPE_MPMU, MPMU_ISCCR,
BIT(31), BIT(31), 0x0,
- 50, 1, 0);
+ 200, 1, 0);
static SPACEMIT_CCU_GATE_FACTOR(i2s_bclk, "i2s_bclk", "i2s_sysclk",
BASE_TYPE_MPMU, MPMU_ISCCR,
BIT(29), BIT(29), 0x0,
diff --git a/drivers/gpu/drm/img-rogue/rgxtimecorr.c b/drivers/gpu/drm/img-rogue/rgxtimecorr.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/img-rogue/rgxtimecorr.c
+++ b/drivers/gpu/drm/img-rogue/rgxtimecorr.c
@@ -428,7 +428,7 @@ static inline IMG_UINT32 _RGXGPUFreqGetIndex(RGX_GPU_DVFS_TABLE *psGpuDVFSTable,
i--;
- PVR_DPF((PVR_DBG_ERROR, "GPU frequency table in the driver is full! "
+ PVR_DPF((PVR_DBG_WARNING, "GPU frequency table in the driver is full! "
"Table size should be increased! Overriding last entry (%u) with %u",
paui32GPUFrequencies[i], ui32CoreClockSpeed));
diff --git a/drivers/gpu/drm/spacemit/Kconfig b/drivers/gpu/drm/spacemit/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/Kconfig
+++ b/drivers/gpu/drm/spacemit/Kconfig
@@ -33,4 +33,18 @@ config DRM_LT8911EXB
select DRM_DP_AUX_BUS
help
- Support for Lontium LT8911EXB DSI to eDP driver.
\ No newline at end of file
+ Support for Lontium LT8911EXB DSI to eDP driver.
+
+config DRM_LT9711
+ tristate "Lontium LT9711 DSI to DP"
+ default y
+ depends on DRM_SPACEMIT
+ select DRM_KMS_HELPER
+ select REGMAP_I2C
+ select DRM_PANEL
+ select DRM_MIPI_DSI
+ select AUXILIARY_BUS
+ select DRM_DP_AUX_BUS
+
+ help
+ Support for Lontium LT9711 DSI to eDP driver.
diff --git a/drivers/gpu/drm/spacemit/Makefile b/drivers/gpu/drm/spacemit/Makefile
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/Makefile
+++ b/drivers/gpu/drm/spacemit/Makefile
@@ -29,4 +29,6 @@ obj-$(CONFIG_DRM_SPACEMIT) += spacemit-drm.o
obj-$(CONFIG_DRM_LT8911EXB) += lt8911exb.o
+obj-$(CONFIG_DRM_LT9711) += lt9711.o
+
obj-$(CONFIG_SPACEMIT_MIPI_PANEL) += spacemit_mipi_panel.o
diff --git a/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c b/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c
+++ b/drivers/gpu/drm/spacemit/dphy/spacemit_dphy_drv.c
@@ -211,7 +211,7 @@ static void dphy_set_timing(struct spacemit_dphy_ctx *dphy_ctx)
| (ta_go << CFG_DPHY_TIME_TA_GO_SHIFT)
| (wakeup << CFG_DPHY_TIME_WAKEUP_SHIFT);
- DRM_INFO("%s dphy time1 ta_get %d ta_go %d wakeup %d reg 0x%x\n", __func__, ta_get, ta_go, wakeup, reg);
+ DRM_DEBUG("%s dphy time1 ta_get %d ta_go %d wakeup %d reg 0x%x\n", __func__, ta_get, ta_go, wakeup, reg);
#ifdef DPTC_DPHY_TEST
dptc_dsi_write(0x44, 0x0403001F);
#else
@@ -223,7 +223,7 @@ static void dphy_set_timing(struct spacemit_dphy_ctx *dphy_ctx)
| (ck_zero << CFG_DPHY_TIME_CLK_ZERO_SHIFT)
| (lpx_clk << CFG_DPHY_TIME_CLK_LPX_SHIFT);
- DRM_INFO("%s dphy time2 ck_exit %d ck_trail %d ck_zero %d lpx_clk %d reg 0x%x\n", __func__, ck_exit, ck_trail, ck_zero, lpx_clk, reg);
+ DRM_DEBUG("%s dphy time2 ck_exit %d ck_trail %d ck_zero %d lpx_clk %d reg 0x%x\n", __func__, ck_exit, ck_trail, ck_zero, lpx_clk, reg);
#ifdef DPTC_DPHY_TEST
dptc_dsi_write(0x48, 0x02010500);
#else
@@ -234,7 +234,7 @@ static void dphy_set_timing(struct spacemit_dphy_ctx *dphy_ctx)
reg = (lpx_clk << CFG_DPHY_TIME_LPX_SHIFT)
| phy_timing->req_ready << CFG_DPHY_TIME_REQRDY_SHIFT;
- DRM_INFO("%s dphy time3 lpx_clk %d req_ready %d reg 0x%x\n", __func__, lpx_clk, phy_timing->req_ready, reg);
+ DRM_DEBUG("%s dphy time3 lpx_clk %d req_ready %d reg 0x%x\n", __func__, lpx_clk, phy_timing->req_ready, reg);
#ifdef DPTC_DPHY_TEST
dptc_dsi_write(0x4c, 0x001F);
#else
diff --git a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
+++ b/drivers/gpu/drm/spacemit/dpu/dpu_saturn.c
@@ -643,15 +643,15 @@ static int dpu_enable_clocks(struct spacemit_dpu *dpu)
}
clk_val = clk_get_rate(clk_ctx->pxclk);
- DRM_INFO("get pxclk=%lld\n", clk_val);
+ DRM_DEBUG("get pxclk=%lld\n", clk_val);
clk_val = clk_get_rate(clk_ctx->mclk);
- DRM_INFO("get mclk=%lld\n", clk_val);
+ DRM_DEBUG("get mclk=%lld\n", clk_val);
clk_val = clk_get_rate(clk_ctx->hclk);
- DRM_INFO("get hclk=%lld\n", clk_val);
+ DRM_DEBUG("get hclk=%lld\n", clk_val);
clk_val = clk_get_rate(clk_ctx->escclk);
- DRM_INFO("get escclk=%lld\n", clk_val);
+ DRM_DEBUG("get escclk=%lld\n", clk_val);
clk_val = clk_get_rate(clk_ctx->bitclk);
- DRM_INFO("get bitclk=%lld\n", clk_val);
+ DRM_DEBUG("get bitclk=%lld\n", clk_val);
udelay(10);
}
diff --git a/drivers/gpu/drm/spacemit/lt8911exb.c b/drivers/gpu/drm/spacemit/lt8911exb.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/lt8911exb.c
+++ b/drivers/gpu/drm/spacemit/lt8911exb.c
@@ -18,12 +18,9 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/media-bus-format.h>
-
#include <linux/atomic.h>
#include <linux/workqueue.h>
-
#include <asm/unaligned.h>
-
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
@@ -41,12 +38,12 @@
#define EDID_SEG_SIZE 256
#define EDID_LEN 16
-// #define _Test_Pattern_
-
#define MIPI_DSI_1920x1080 1
#define MIPI_DSI_1920x1200 0
-#define _uart_debug_
+// #define _test_pattern_
+// #define _read_edid_
+// #define _uart_debug_
#define _eDP_2G7_
#define _link_train_enable_
@@ -72,13 +69,13 @@ static int Nvid_Val[] = {0x0080, 0x0800};
static int MIPI_Timing[] =
// hfp, hs, hbp, hact, htotal, vfp, vs, vbp, vact, vtotal, pixel_CLK/10000
-//1920x1080
+// 1920x1080
#if MIPI_DSI_1920x1080
// {48, 32, 200, 1920, 2200, 3, 6, 31, 1080, 1120, 14784}; // boe config for linux
{48, 32, 200, 1920, 2200, 3, 6, 31, 1080, 1120, 14285}; // boe config for linux
#endif
-//1920x1200
+// 1920x1200
#if MIPI_DSI_1920x1200
// {16, 16, 298, 1920, 2250, 3, 14, 19, 1200, 1236, 16684}; // boe config for linux
{16, 16, 298, 1920, 2250, 3, 14, 19, 1200, 1236, 15360}; // boe config for linux
@@ -108,7 +105,7 @@ bool EDID_Reply = 0;
bool ScrambleMode = 0;
static const struct drm_display_mode lt8911exb_panel_modes[] = {
-//1920x1080
+// 1920x1080
#if MIPI_DSI_1920x1080
{
.clock = 142857143 / 1000,
@@ -141,7 +138,6 @@ static const struct drm_display_mode lt8911exb_panel_modes[] = {
};
-
enum
{
_Level0_ = 0, // 27.8 mA 0x83/0x00
@@ -151,12 +147,12 @@ enum
_Level4_, // 21.4 mA 0x82/0x80
_Level5_, // 18.2 mA 0x82/0x40
_Level6_, // 16.6 mA 0x82/0x20
- _Level7_, // 15mA 0x82/0x00 // level 1
+ _Level7_, // 15 mA 0x82/0x00 // level 1
_Level8_, // 12.8mA 0x81/0x00 // level 2
_Level9_, // 11.2mA 0x80/0xe0 // level 3
_Level10_, // 9.6mA 0x80/0xc0 // level 4
- _Level11_, // 8mA 0x80/0xa0 // level 5
- _Level12_, // 6mA 0x80/0x80 // level 6
+ _Level11_, // 8mA 0x80/0xa0 // level 5
+ _Level12_, // 6mA 0x80/0x80 // level 6
};
u8 Swing_Setting1[] = {0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x80, 0x80, 0x80, 0x80};
@@ -176,12 +172,10 @@ struct lt8911exb {
struct mipi_dsi_device *dsi0;
struct mipi_dsi_device *dsi1;
- //bool ac_mode;
- struct gpio_desc *reset_gpio; //reset
- struct gpio_desc *enable_gpio; //power
- struct gpio_desc *standby_gpio; //standby
-
- struct gpio_desc *bl_gpio; //backlight
+ struct gpio_desc *reset_gpio; //reset
+ struct gpio_desc *enable_gpio; //power
+ struct gpio_desc *standby_gpio; //standby
+ struct gpio_desc *bl_gpio; //backlight
bool power_on;
bool sleep;
@@ -201,25 +195,20 @@ struct lt8911exb {
bool init_work_pending;
};
-
static const struct regmap_config lt8911exb_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff,
};
-
static struct lt8911exb *panel_to_lt8911exb(struct drm_panel *panel)
{
return container_of(panel, struct lt8911exb, base);
}
-
-//--------------------------------------enable function-------------------------------//
-
void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
{
- unsigned int tmp;
+ __maybe_unused unsigned int tmp;
regmap_write(lt8911exb->regmap, 0xff, 0xd0);
regmap_write(lt8911exb->regmap, 0x0d, (MIPI_Timing[vtotal] / 256));
@@ -230,14 +219,14 @@ void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
regmap_write(lt8911exb->regmap, 0x12, (MIPI_Timing[htotal] % 256)); //htotal
regmap_write(lt8911exb->regmap, 0x13, (MIPI_Timing[hact] / 256));
regmap_write(lt8911exb->regmap, 0x14, (MIPI_Timing[hact] % 256)); //hactive
- regmap_write(lt8911exb->regmap, 0x15, (MIPI_Timing[vs] % 256)); //vsa
- regmap_write(lt8911exb->regmap, 0x16, (MIPI_Timing[hs] % 256)); //hsa
+ regmap_write(lt8911exb->regmap, 0x15, (MIPI_Timing[vs] % 256)); //vsa
+ regmap_write(lt8911exb->regmap, 0x16, (MIPI_Timing[hs] % 256)); //hsa
regmap_write(lt8911exb->regmap, 0x17, (MIPI_Timing[vfp] / 256));
regmap_write(lt8911exb->regmap, 0x18, (MIPI_Timing[vfp] % 256)); //vfp
regmap_write(lt8911exb->regmap, 0x19, (MIPI_Timing[hfp] / 256));
regmap_write(lt8911exb->regmap, 0x1a, (MIPI_Timing[hfp] % 256)); //hfp
-
+#ifdef _uart_debug_
DRM_INFO("------\n");
DRM_INFO("MIPI_Timing[vtotal] / 256 = %d\n", MIPI_Timing[vtotal] / 256);
DRM_INFO("MIPI_Timing[vtotal] 256 = %d\n", MIPI_Timing[vtotal] % 256);
@@ -257,7 +246,6 @@ void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
DRM_INFO("MIPI_Timing[hfp] 256 = %d\n", MIPI_Timing[hfp] % 256);
DRM_INFO("------\n");
-
regmap_read(lt8911exb->regmap, 0x0d, &tmp);
DRM_DEBUG_ATOMIC("0x0d = %d\n",tmp);
regmap_read(lt8911exb->regmap, 0x0e, &tmp);
@@ -290,11 +278,12 @@ void lt8911exb_mipi_video_timing(struct lt8911exb *lt8911exb)
DRM_DEBUG_ATOMIC("0x19 = %d\n",tmp);
regmap_read(lt8911exb->regmap, 0x1a, &tmp);
DRM_DEBUG_ATOMIC("0x1a = %d\n",tmp);
+#endif
}
void lt8911exb_edp_video_cfg(struct lt8911exb *lt8911exb)
{
- unsigned int tmp;
+ __maybe_unused unsigned int tmp;
regmap_write(lt8911exb->regmap, 0xff, 0xa8);
regmap_write(lt8911exb->regmap, 0x2d, 0x88); // MSA from register
@@ -314,6 +303,7 @@ void lt8911exb_edp_video_cfg(struct lt8911exb *lt8911exb)
regmap_write(lt8911exb->regmap, 0x15, (MIPI_Timing[vact] / 256));
regmap_write(lt8911exb->regmap, 0x16, (MIPI_Timing[vact] % 256));
+#ifdef _uart_debug_
DRM_INFO("------\n");
DRM_INFO("(u8)( MIPI_Timing[htotal] / 256 ) = %d\n", (MIPI_Timing[htotal] / 256));
DRM_INFO("(u8)( MIPI_Timing[htotal] 256 ) = %d\n", (MIPI_Timing[htotal] % 256));
@@ -366,14 +356,16 @@ void lt8911exb_edp_video_cfg(struct lt8911exb *lt8911exb)
DRM_DEBUG_ATOMIC("0x15 = %d\n",tmp);
regmap_read(lt8911exb->regmap, 0x16, &tmp);
DRM_DEBUG_ATOMIC("0x16 = %d\n",tmp);
+#endif
}
void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
{
+#ifdef _read_edid_
u8 i, j;
unsigned int reg;
- DRM_INFO("lt8911exb_read_edid\n");
+ DRM_INFO("%s()\n", __func__);
regmap_write(lt8911exb->regmap, 0xff, 0xac );
regmap_write(lt8911exb->regmap, 0x00, 0x20 ); //Soft Link train
@@ -408,7 +400,7 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
regmap_write(lt8911exb->regmap, 0x2b, 0x50 );
regmap_write(lt8911exb->regmap, 0x2b, 0x0f );
regmap_write(lt8911exb->regmap, 0x2c, 0x00 ); //start Aux read edid
- mdelay(50); //more than 50ms
+ mdelay(50); //more than 50ms
regmap_read(lt8911exb->regmap, 0x39, &reg);
DRM_INFO("lt8911exb_read_edid 0x39 0x%x\n", reg);
@@ -429,16 +421,16 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
return;
}
}
-#if 0
+
for( i = 0; i < 128; i++ ) //print edid data
{
if( ( i % 16 ) == 0 )
{
- printk( "\n" );
+ DRM_INFO( "\n" );
}
- printk( "%x", EDID_DATA[i] );
+ DRM_INFO( "%x", EDID_DATA[i] );
}
-#endif
+
EDID_Timing[hfp] = (EDID_DATA[0x41] & 0xC0) * 4 + EDID_DATA[0x3e];
EDID_Timing[hs] = (EDID_DATA[0x41] & 0x30) * 16 + EDID_DATA[0x3f];
@@ -451,14 +443,15 @@ void lt8911exb_read_edid(struct lt8911exb *lt8911exb)
EDID_Timing[vact] = (EDID_DATA[0x3d] & 0xf0) * 16 + EDID_DATA[0x3b];
EDID_Timing[vtotal] = (EDID_DATA[0x3d] & 0xf0 ) * 16 + EDID_DATA[0x3b] + ((EDID_DATA[0x3d] & 0x03) * 0x100 + EDID_DATA[0x3c]);
EDID_Timing[pclk_10khz] = EDID_DATA[0x37] * 0x100 + EDID_DATA[0x36];
- printk( "eDP Timing = { H_FP / H_pluse / H_BP / H_act / H_tol / V_FP / V_pluse / V_BP / V_act / V_tol / D_CLK };" );
- printk( "eDP Timing = { %d %d %d %d %d %d %d %d %d %d %d };\n",
+ DRM_INFO( "eDP Timing = { H_FP / H_pluse / H_BP / H_act / H_tol / V_FP / V_pluse / V_BP / V_act / V_tol / D_CLK };" );
+ DRM_INFO( "eDP Timing = { %d %d %d %d %d %d %d %d %d %d %d };\n",
(u32)EDID_Timing[hfp],(u32)EDID_Timing[hs],(u32)EDID_Timing[hbp],(u32)EDID_Timing[hact],(u32)EDID_Timing[htotal],
(u32)EDID_Timing[vfp],(u32)EDID_Timing[vs],(u32)EDID_Timing[vbp],(u32)EDID_Timing[vact],(u32)EDID_Timing[vtotal],(u32)EDID_Timing[pclk_10khz]);
}
return;
+#endif
}
void lt8911exb_setup(struct lt8911exb *lt8911exb)
@@ -469,7 +462,7 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
u16 Temp16;
u32 chip_read = 0x00;
- DRM_INFO("\r\n lt8911exb_setup");
+ DRM_DEBUG("\r\n lt8911exb_setup");
/* init */
regmap_write(lt8911exb->regmap, 0xff, 0x81); // Change Reg bank
@@ -584,13 +577,13 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
/*stage2 hs mode*/
// regmap_write(lt8911exb->regmap, 0x1e, 0x0A); //regmap_write(lt8911exb->regmap, 0x1e, 0x01 ); // 0x11
- DRM_INFO("\r\n lt8911exb_setup 0X1e 0x0a");
+ DRM_DEBUG("\r\n lt8911exb_setup 0X1e 0x0a");
regmap_write(lt8911exb->regmap, 0x1e, 0x0a);
regmap_write(lt8911exb->regmap, 0x23, 0xf0); // 0x80
regmap_write(lt8911exb->regmap, 0x2b, 0x80); // 0xa0
-#ifdef _Test_Pattern_
+#ifdef _test_pattern_
regmap_write(lt8911exb->regmap, 0x26, (pcr_m | 0x80));
#else
@@ -683,10 +676,10 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
mdelay(5);
regmap_read(lt8911exb->regmap, 0x37, &chip_read);
if (chip_read & 0x02) {
- DRM_INFO("\r\n LT8911 tx pll locked");
+ DRM_DEBUG("\r\n LT8911 tx pll locked");
break;
} else {
- DRM_INFO("\r\n LT8911 tx pll unlocked");
+ DRM_DEBUG("\r\n LT8911 tx pll unlocked");
regmap_write(lt8911exb->regmap, 0xff, 0x81);
regmap_write(lt8911exb->regmap, 0x09, 0xfc);
regmap_write(lt8911exb->regmap, 0x09, 0xfd);
@@ -721,7 +714,7 @@ void lt8911exb_setup(struct lt8911exb *lt8911exb)
/*eDP Tx Digital */
regmap_write(lt8911exb->regmap, 0xff, 0xa8); // Change Reg bank
-#ifdef _Test_Pattern_
+#ifdef _test_pattern_
regmap_write(lt8911exb->regmap, 0x24, 0x50); // bit2 ~ bit 0 : test panttern image mode
regmap_write(lt8911exb->regmap, 0x25, 0x70); // bit6 ~ bit 4 : test Pattern color
@@ -767,7 +760,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
regmap_write(lt8911exb->regmap, 0xa1, 0x02 ); // DP scramble mode;
}
-// regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // 0xf0:Close scramble; 0xD0 : Open scramble
+ //regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // 0xf0:Close scramble; 0xD0 : Open scramble
regmap_write(lt8911exb->regmap, 0xff, 0x81);
regmap_write(lt8911exb->regmap, 0x09, 0x7d);
@@ -793,11 +786,11 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
DRM_DEBUG_ATOMIC("1-2 reg = %d\n",reg);
- DRM_INFO( "\r\nvideo check: mipi byteclk = %d ", reg ); // mipi byteclk = reg * 1000
- DRM_INFO( "\r\nvideo check: mipi bitrate = %d ", reg * 8); // mipi byteclk = reg * 1000
- DRM_INFO( "\r\nvideo check: mipi pclk = %d ", reg /3 * 4 * 1000); // mipi byteclk = reg * 1000
+ DRM_DEBUG( "\r\nvideo check: mipi byteclk = %d ", reg ); // mipi byteclk = reg * 1000
+ DRM_DEBUG( "\r\nvideo check: mipi bitrate = %d ", reg * 8); // mipi byteclk = reg * 1000
+ DRM_DEBUG( "\r\nvideo check: mipi pclk = %d ", reg /3 * 4 * 1000); // mipi byteclk = reg * 1000
} else {
- DRM_INFO( "\r\nvideo check: mipi clk unstable" );
+ DRM_DEBUG( "\r\nvideo check: mipi clk unstable" );
}
/* mipi vtotal check*/
@@ -810,7 +803,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
reg = reg * 256 + temp2;
DRM_DEBUG_ATOMIC("2-1 reg = %d\n",reg);
- DRM_INFO( "\r\nvideo check: Vtotal = %d", reg);
+ DRM_DEBUG( "\r\nvideo check: Vtotal = %d", reg);
/* mipi word count check*/
regmap_write(lt8911exb->regmap, 0xff, 0xd0);
@@ -826,7 +819,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
DRM_DEBUG_ATOMIC( "\r\n3-1 reg = %d ", reg );
- DRM_INFO( "\r\nvideo check: Hact(word counter) = %d", reg);
+ DRM_DEBUG( "\r\nvideo check: Hact(word counter) = %d", reg);
/* mipi Vact check*/
//reg = LT8911EXB_IIC_Read_byte( 0x85 );
@@ -838,7 +831,7 @@ void lt8911exb_video_check(struct lt8911exb *lt8911exb)
reg = reg * 256 + temp2;
DRM_DEBUG_ATOMIC( "\r\n4-1 reg = %d ", reg );
- DRM_INFO( "\r\nvideo check: Vact = %d", reg);
+ DRM_DEBUG( "\r\nvideo check: Vact = %d", reg);
}
@@ -904,7 +897,6 @@ unsigned int DpcdRead( struct lt8911exb *lt8911exb, u32 Address )
regmap_write(lt8911exb->regmap, 0x2c, 0x00); //start Aux read edid
mdelay(50); //more than 10ms
- //reg = LT8911EXB_IIC_Read_byte( 0x25 );
regmap_read(lt8911exb->regmap, 0x25, &reg);
if ((reg & 0x0f) == 0x0c) {
regmap_read(lt8911exb->regmap, 0x39, &temp);
@@ -935,7 +927,7 @@ void lt8911exb_link_train(struct lt8911exb *lt8911exb)
regmap_write(lt8911exb->regmap, 0xff, 0x85);
-// regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // turn off scramble
+ //regmap_write(lt8911exb->regmap, 0x17, 0xf0 ); // turn off scramble
if (ScrambleMode) {
regmap_write(lt8911exb->regmap, 0xa1, 0x82); // eDP scramble mode;
@@ -999,16 +991,11 @@ void lt8911exb_reset(struct lt8911exb *lt8911exb)
}
gpiod_direction_output(lt8911exb->reset_gpio, 1);
-
usleep_range(100*1000, 150*1000); //150ms
gpiod_direction_output(lt8911exb->reset_gpio, 0);
-
usleep_range(100*1000, 150*1000); //150ms
gpiod_direction_output(lt8911exb->reset_gpio, 1);
-
usleep_range(100*1000, 150*1000); //150ms
- // gpiod_direction_input(lt8911exb->reset_gpio);
- // usleep_range(100*1000, 150*1000); //150ms
}
void LT8911EX_TxSwingPreSet(struct lt8911exb *lt8911exb)
@@ -1031,25 +1018,20 @@ void LT8911EXB_LinkTrainResultCheck( struct lt8911exb *lt8911exb)
{
#ifdef _link_train_enable_
u8 i;
- //u8 val;
unsigned int val;
- //int ret;
regmap_write(lt8911exb->regmap, 0xff, 0xac);
for (i = 0; i < 10; i++) {
- //val = LT8911EXB_IIC_Read_byte( 0x82 );
regmap_read(lt8911exb->regmap, 0x82, &val);
- DRM_INFO("\r\n0x82: 0x%x", val);
+ DRM_DEBUG("\r\n0x82: 0x%x", val);
if (val & 0x20) {
if ((val & 0x1f) == 0x1e) {
#ifdef _uart_debug_
- // DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: edp link train successed: 0x%bx", val);
DRM_INFO("\r\nedp link train successed: 0x%x", val);
#endif
return;
} else {
#ifdef _uart_debug_
- //DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: edp link train failed: 0x%bx", val);
DRM_INFO("\r\nedp link train failed: 0x%x", val);
#endif
regmap_write(lt8911exb->regmap, 0xff, 0xac);
@@ -1061,16 +1043,13 @@ void LT8911EXB_LinkTrainResultCheck( struct lt8911exb *lt8911exb)
regmap_write(lt8911exb->regmap, 0x14, 0x84);
mdelay(50);
regmap_write(lt8911exb->regmap, 0x14, 0xc0);
- //DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: Enable eDP video output while linktrian fail");
}
#ifdef _uart_debug_
- //val = LT8911EXB_IIC_Read_byte( 0x83 );
regmap_read(lt8911exb->regmap, 0x83, &val);
//DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: panel link rate: 0x%bx",val);
DRM_INFO( "\r\npanel link rate: 0x%x", val );
- //val = LT8911EXB_IIC_Read_byte( 0x84 );
regmap_read(lt8911exb->regmap, 0x84, &val);
//DRM_DEBUG_ATOMIC("\r\nLT8911_LinkTrainResultCheck: panel link count: 0x%bx",val);
DRM_INFO( "\r\npanel link count:0x%x ", val);
@@ -1092,24 +1071,22 @@ void LT8911EX_link_train_result(struct lt8911exb *lt8911exb)
unsigned int temp;
regmap_write(lt8911exb->regmap, 0xff, 0xac);
for (i = 0; i < 10; i++) {
- //reg = LT8911EXB_IIC_Read_byte( 0x82 );
regmap_read(lt8911exb->regmap, 0x82, &reg);
- // Debug_DispStrNum( "\r\n0x82 = ", reg );
- DRM_INFO( "\r\n0x82 = 0x%x", reg );
+ DRM_DEBUG( "\r\n0x82 = 0x%x", reg );
if (reg & 0x20) {
if((reg & 0x1f) == 0x1e) {
- DRM_INFO("\r\nLink train success, 0x82 = 0x%x", reg);
+ DRM_DEBUG("\r\nLink train success, 0x82 = 0x%x", reg);
} else {
- DRM_INFO("\r\nLink train fail, 0x82 = 0x%x", reg);
+ DRM_DEBUG("\r\nLink train fail, 0x82 = 0x%x", reg);
}
regmap_read(lt8911exb->regmap, 0x83, &temp);
- DRM_INFO("\r\npanel link rate: 0x%x", temp);
+ DRM_DEBUG("\r\npanel link rate: 0x%x", temp);
regmap_read(lt8911exb->regmap, 0x84, &temp);
- DRM_INFO("\r\npanel link count: 0x%x", temp);
+ DRM_DEBUG("\r\npanel link count: 0x%x", temp);
return;
} else {
- DRM_INFO("\r\nlink trian on going...");
+ DRM_DEBUG("\r\nlink trian on going...");
}
mdelay(100);
}
@@ -1136,11 +1113,7 @@ void PCR_Status(struct lt8911exb *lt8911exb) // for debug
#endif
}
-
-//--------------------------------------enable function-------------------------------//
-
-
-static int lt8911exb_i2c_test(struct lt8911exb *lt8911exb)
+static int lt8911exb_chip_id(struct lt8911exb *lt8911exb)
{
u8 retry = 0;
unsigned int chip_id_h = 0, chip_id_m = 0, chip_id_l = 0;
@@ -1165,12 +1138,7 @@ static int lt8911exb_i2c_test(struct lt8911exb *lt8911exb)
regmap_read(lt8911exb->regmap, 0x01, &chip_id_m);
regmap_read(lt8911exb->regmap, 0x02, &chip_id_h);
// LT8911EXB i2c test success chipid: 0xe0517
- dev_info(lt8911exb->dev, "LT8911EXB i2c test success chipid: 0x%x%x%x\n", chip_id_h, chip_id_m, chip_id_l);
-
-// if (chip_id_h == 0 && chip_id_l == 0) {
-// dev_err(&client->dev, "LT8911EXB i2c test failed time %d\n", retry);
-// continue;
-// }
+ DRM_DEBUG("LT8911EXB i2c test success chipid: 0x%x%x%x\n", chip_id_h, chip_id_m, chip_id_l);
ret = 0;
break;
@@ -1183,47 +1151,19 @@ static int lt8911exb_panel_enable(struct drm_panel *panel)
{
struct lt8911exb *lt8911exb = panel_to_lt8911exb(panel);
- DRM_INFO(" %s() \n", __func__);
+ DRM_INFO("%s()\n", __func__);
- #if 0
gpiod_direction_output(lt8911exb->enable_gpio, 1);
usleep_range(100*1000, 150*1000); //150ms
+ gpiod_direction_output(lt8911exb->standby_gpio, 1);
+ usleep_range(100*1000, 150*1000); //150ms
- lt8911exb_reset(lt8911exb);
- lt8911exb_i2c_test(lt8911exb);
- lt8911exb_edp_video_cfg(lt8911exb); //void lt8911exb_edp_video_cfg( void )
- lt8911exb_setup(lt8911exb); //void LT8911EXB_init( void )
-
- ScrambleMode = 0;
-
- LT8911EX_TxSwingPreSet(lt8911exb);
- lt8911exb_link_train(lt8911exb); //void LT8911EX_link_train( void )
- LT8911EXB_LinkTrainResultCheck(lt8911exb);
- LT8911EX_link_train_result(lt8911exb);
- lt8911exb_video_check(lt8911exb); //just for Check MIPI Input //void LT8911EXB_video_check( void )
-
- // DRM_DEBUG_ATOMIC("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
- DRM_INFO("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
-
- PCR_Status(lt8911exb);
- #endif
+ gpiod_direction_output(lt8911exb->bl_gpio, 1);
schedule_delayed_work(&lt8911exb->init_work,
- msecs_to_jiffies(5000));
+ msecs_to_jiffies(2000));
lt8911exb->init_work_pending = true;
-
- #if 0
- // gpiod_direction_output(lt8911exb->enable_gpio, LT8911_LOW);
- gpiod_direction_output(lt8911exb->enable_gpio, 0);
-
- usleep_range(100*1000, 150*1000); //150ms
- // gpiod_direction_output(lt8911exb->enable_gpio, LT8911_HIGH);
- gpiod_direction_output(lt8911exb->enable_gpio, 1);
-
- usleep_range(100*1000, 150*1000); //150ms
- #endif
-
return 0;
}
@@ -1231,8 +1171,12 @@ static int lt8911exb_panel_disable(struct drm_panel *panel)
{
struct lt8911exb *lt8911exb = panel_to_lt8911exb(panel);
- DRM_INFO(" %s() \n", __func__);
+ DRM_INFO("%s()\n", __func__);
+
+ gpiod_direction_output(lt8911exb->bl_gpio, 0);
+ gpiod_direction_output(lt8911exb->standby_gpio, 0);
+ usleep_range(100*1000, 150*1000); //150ms
gpiod_direction_output(lt8911exb->enable_gpio, 0);
usleep_range(100*1000, 150*1000); //150ms
@@ -1250,7 +1194,7 @@ static int lt8911exb_panel_get_modes(struct drm_panel *panel,
unsigned int i, num = 0;
static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
- DRM_INFO(" %s() \n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
for (i = 0; i < ARRAY_SIZE(lt8911exb_panel_modes); i++) {
const struct drm_display_mode *m = &lt8911exb_panel_modes[i];
@@ -1303,14 +1247,14 @@ static void init_work_func(struct work_struct *work)
struct lt8911exb *lt8911exb = container_of(work, struct lt8911exb,
init_work.work);
- DRM_INFO(" %s() \n", __func__);
+ DRM_DEBUG(" %s() \n", __func__);
gpiod_direction_output(lt8911exb->enable_gpio, 1);
usleep_range(100*1000, 150*1000); //150ms
lt8911exb_reset(lt8911exb);
- lt8911exb_i2c_test(lt8911exb);
+ lt8911exb_chip_id(lt8911exb);
lt8911exb_edp_video_cfg(lt8911exb);
lt8911exb_setup(lt8911exb);
@@ -1324,8 +1268,7 @@ static void init_work_func(struct work_struct *work)
LT8911EX_link_train_result(lt8911exb);
lt8911exb_video_check(lt8911exb); //just for Check MIPI Input
- // DRM_DEBUG_ATOMIC("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
- DRM_INFO("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
+ DRM_DEBUG("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(lt8911exb, 0x0202));
PCR_Status(lt8911exb);
@@ -1343,18 +1286,17 @@ static int lt8911exb_probe(struct i2c_client *client,
struct device_node *lcd_node;
int rc;
- // const void *p;
const char *str;
char lcd_path[60];
const char *lcd_name;
struct mipi_dsi_device_info info = {
.type = IT8911_DSI_DRIVER_NAME,
- .channel = 0, //0,
+ .channel = 0,
.node = NULL,
};
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "Failed check I2C functionality");
@@ -1402,12 +1344,7 @@ static int lt8911exb_probe(struct i2c_client *client,
return PTR_ERR(lt8911exb->reset_gpio);
}
- gpiod_direction_output(lt8911exb->reset_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
- gpiod_direction_output(lt8911exb->reset_gpio, 0);
- usleep_range(100*1000, 150*1000); //150ms
- gpiod_direction_output(lt8911exb->reset_gpio, 1);
- usleep_range(100*1000, 150*1000); //150ms
+ lt8911exb_reset(lt8911exb);
lt8911exb->bl_gpio = devm_gpiod_get_optional(dev, "bl",
GPIOD_IN);
@@ -1420,7 +1357,7 @@ static int lt8911exb_probe(struct i2c_client *client,
i2c_set_clientdata(client, lt8911exb);
//check i2c communicate
- ret = lt8911exb_i2c_test(lt8911exb); //void LT8911EX_ChipID( void )
+ ret = lt8911exb_chip_id(lt8911exb);
if (ret < 0) {
dev_err(&client->dev, "Failed communicate with IC use I2C\n");
return ret;
@@ -1430,14 +1367,10 @@ static int lt8911exb_probe(struct i2c_client *client,
if (!endpoint)
return -ENODEV;
- DRM_INFO(" %s() endpoint %s\n", __func__, endpoint->full_name);
-
dsi_host_node = of_graph_get_remote_port_parent(endpoint);
if (!dsi_host_node)
goto error;
- DRM_INFO(" %s() dsi_host_node %s\n", __func__, dsi_host_node->full_name);
-
rc = of_property_read_string(dsi_host_node, "force-attached", &str);
if (!rc)
lcd_name = str;
@@ -1452,7 +1385,6 @@ static int lt8911exb_probe(struct i2c_client *client,
DRM_INFO("%pOF: find %s node\n", dsi_host_node, lcd_name);
-
host = of_find_mipi_dsi_host_by_node(dsi_host_node);
of_node_put(dsi_host_node);
if (!host) {
@@ -1461,7 +1393,7 @@ static int lt8911exb_probe(struct i2c_client *client,
}
drm_panel_init(&lt8911exb->base, dev, &lt8911exb_panel_funcs,
- DRM_MODE_CONNECTOR_eDP);//DRM_MODE_CONNECTOR_eDP DRM_MODE_CONNECTOR_DSI
+ DRM_MODE_CONNECTOR_DSI);
/* This appears last, as it's what will unblock the DSI host
* driver's component bind function.
@@ -1474,7 +1406,6 @@ static int lt8911exb_probe(struct i2c_client *client,
goto error;
of_node_put(endpoint);
-
lt8911exb->dsi = mipi_dsi_device_register_full(host, &info);
if (IS_ERR(lt8911exb->dsi)) {
dev_err(dev, "DSI device registration failed: %ld\n",
@@ -1494,7 +1425,7 @@ static void lt8911exb_remove(struct i2c_client *client)
{
struct lt8911exb *lt8911exb = i2c_get_clientdata(client);
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
mipi_dsi_detach(lt8911exb->dsi);
@@ -1529,11 +1460,9 @@ static int lt8911exb_dsi_probe(struct mipi_dsi_device *dsi)
{
int ret;
-
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
dsi->lanes = 4;
-
dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM);
@@ -1548,9 +1477,18 @@ static int lt8911exb_dsi_probe(struct mipi_dsi_device *dsi)
return ret;
}
+static const struct of_device_id spacemit_edp_of_match[] = {
+ { .compatible = "spacemit,edp-panel" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spacemit_edp_of_match);
+
static struct mipi_dsi_driver lt8911exb_dsi_driver = {
- .driver.name = IT8911_DSI_DRIVER_NAME,
.probe = lt8911exb_dsi_probe,
+ .driver = {
+ .name = IT8911_DSI_DRIVER_NAME,
+ .of_match_table = spacemit_edp_of_match,
+ },
};
@@ -1559,7 +1497,6 @@ static int __init init_lt8911exb(void)
int err;
DRM_INFO("%s()\n", __func__);
-
mipi_dsi_driver_register(&lt8911exb_dsi_driver);
err = i2c_add_driver(&lt8911exb_driver);
@@ -1571,7 +1508,6 @@ module_init(init_lt8911exb);
static void __exit exit_lt8911exb(void)
{
DRM_INFO("%s()\n", __func__);
-
i2c_del_driver(&lt8911exb_driver);
mipi_dsi_driver_unregister(&lt8911exb_dsi_driver);
}
diff --git a/drivers/gpu/drm/spacemit/lt9711.c b/drivers/gpu/drm/spacemit/lt9711.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/gpu/drm/spacemit/lt9711.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Spacemit Co., Ltd.
+ *
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/media-bus-format.h>
+#include <linux/atomic.h>
+#include <linux/workqueue.h>
+#include <asm/unaligned.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_bridge.h>
+#include <linux/delay.h>
+#include <drm/display/drm_dp_aux_bus.h>
+#include <drm/display/drm_dp_helper.h>
+
+#define IT9711_DSI_DRIVER_NAME "spacemit-dp-drv"
+#define MIPI_DSI_1920x1080 1
+
+static const struct drm_display_mode lt9711_panel_modes[] = {
+
+#if MIPI_DSI_1920x1080
+ {
+ .clock = 142857143 / 1000,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 88,
+ .hsync_end = 1920 + 88 + 148,
+ .htotal = 1920 + 88 + 148 + 44,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 4,
+ .vsync_end = 1080 + 4 + 36,
+ .vtotal = 1080 + 4 + 36 + 5,
+ },
+#endif
+
+};
+
+struct lt9711 {
+ struct device *dev;
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+
+ struct regmap *regmap;
+
+ struct gpio_desc *reset_gpio;
+
+ struct i2c_client *client;
+ struct drm_panel base;
+ struct mipi_dsi_device *dsi;
+
+ enum drm_connector_status status;
+
+ struct delayed_work init_work;
+ bool init_work_pending;
+};
+
+static const struct regmap_config lt9711_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+};
+
+static struct lt9711 *panel_to_lt9711(struct drm_panel *panel)
+{
+ return container_of(panel, struct lt9711, base);
+}
+
+static int lt9711_i2c_detect(struct lt9711 *lt9711)
+{
+ u8 retry = 0;
+ unsigned int status = 0;
+ int ret = -EAGAIN;
+
+ while(retry++ < 3) {
+
+ ret = regmap_write(lt9711->regmap, 0xff, 0x80);
+ if(ret < 0) {
+ dev_err(lt9711->dev, "LT9711 i2c detect write addr:0xff failed\n");
+ continue;
+ }
+ usleep_range(100*1000, 150*1000); //150ms
+
+ regmap_read(lt9711->regmap, 0xd6, &status);
+ // LT9711 i2c detect success status: 0xee
+ DRM_INFO("LT9711 i2c detect success status: 0x%x\n", status);
+
+ if (0xee == status)
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int lt9711_panel_enable(struct drm_panel *panel)
+{
+ struct lt9711 *lt9711 = panel_to_lt9711(panel);
+
+ DRM_INFO(" %s() \n", __func__);
+
+ schedule_delayed_work(&lt9711->init_work,
+ msecs_to_jiffies(1000));
+ lt9711->init_work_pending = true;
+
+ return 0;
+}
+
+static int lt9711_panel_disable(struct drm_panel *panel)
+{
+ struct lt9711 *lt9711 = panel_to_lt9711(panel);
+
+ DRM_INFO(" %s() \n", __func__);
+
+ if (lt9711->init_work_pending) {
+ cancel_delayed_work_sync(&lt9711->init_work);
+ lt9711->init_work_pending = false;
+ }
+
+ return 0;
+}
+
+static int lt9711_panel_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ unsigned int i, num = 0;
+ static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+ DRM_DEBUG(" %s() \n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(lt9711_panel_modes); i++) {
+ const struct drm_display_mode *m = &lt9711_panel_modes[i];
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, m);
+ if (!mode) {
+ dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
+ m->hdisplay, m->vdisplay,
+ drm_mode_vrefresh(m));
+ continue;
+ }
+
+ mode->type |= DRM_MODE_TYPE_DRIVER;
+
+ if (i == 0)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+ num++;
+ }
+
+ connector->display_info.bpc = 8;
+ // 1920x1080
+ #if MIPI_DSI_1920x1080
+ connector->display_info.width_mm = 309;
+ connector->display_info.height_mm = 174;
+ #endif
+
+ drm_display_info_set_bus_formats(&connector->display_info,
+ &bus_format, 1);
+ return num;
+}
+
+
+static const struct drm_panel_funcs lt9711_panel_funcs = {
+ .disable = lt9711_panel_disable,
+ .enable = lt9711_panel_enable,
+ .get_modes = lt9711_panel_get_modes,
+};
+
+static void init_work_func(struct work_struct *work)
+{
+ struct lt9711 *lt9711 = container_of(work, struct lt9711,
+ init_work.work);
+ DRM_DEBUG(" %s() \n", __func__);
+
+ lt9711_i2c_detect(lt9711);
+
+}
+
+static int lt9711_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lt9711 *lt9711;
+ struct device *dev = &client->dev;
+ int ret;
+
+ struct device_node *endpoint, *dsi_host_node;
+ struct mipi_dsi_host *host;
+
+ struct device_node *lcd_node;
+ int rc;
+ const char *str;
+ char lcd_path[60];
+ const char *lcd_name;
+
+ struct mipi_dsi_device_info info = {
+ .type = IT9711_DSI_DRIVER_NAME,
+ .channel = 0,
+ .node = NULL,
+ };
+
+ DRM_DEBUG("%s()\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "Failed check I2C functionality");
+ return -ENODEV;
+ }
+
+ lt9711 = devm_kzalloc(&client->dev, sizeof(*lt9711), GFP_KERNEL);
+ if (!lt9711)
+ return -ENOMEM;
+
+ lt9711->dev = &client->dev;
+ lt9711->client = client;
+
+ //regmap i2c , maybe useless
+ lt9711->regmap = devm_regmap_init_i2c(client, &lt9711_regmap_config);
+ if (IS_ERR(lt9711->regmap)) {
+ dev_err(lt9711->dev, "regmap i2c init failed\n");
+ return PTR_ERR(lt9711->regmap);
+ }
+
+ i2c_set_clientdata(client, lt9711);
+
+ //check i2c communicate
+ ret = lt9711_i2c_detect(lt9711);
+ if (ret < 0) {
+ DRM_INFO("detect DP failed communicate with IC use I2C\n");
+ return ret;
+ }
+
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!endpoint)
+ return -ENODEV;
+
+ dsi_host_node = of_graph_get_remote_port_parent(endpoint);
+ if (!dsi_host_node)
+ goto error;
+
+ rc = of_property_read_string(dsi_host_node, "force-attached", &str);
+ if (!rc)
+ lcd_name = str;
+
+ sprintf(lcd_path, "/lcds/%s", lcd_name);
+ lcd_node = of_find_node_by_path(lcd_path);
+ if (!lcd_node) {
+ DRM_ERROR("%pOF: could not find %s node\n", dsi_host_node, lcd_name);
+ of_node_put(endpoint);
+ return -ENODEV;
+ }
+
+ DRM_INFO("%pOF: find %s node\n", dsi_host_node, lcd_name);
+
+ host = of_find_mipi_dsi_host_by_node(dsi_host_node);
+ of_node_put(dsi_host_node);
+ if (!host) {
+ of_node_put(endpoint);
+ return -EPROBE_DEFER;
+ }
+
+ drm_panel_init(&lt9711->base, dev, &lt9711_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ /* This appears last, as it's what will unblock the DSI host
+ * driver's component bind function.
+ */
+ drm_panel_add(&lt9711->base);
+
+ lt9711->base.dev->of_node = lcd_node;
+ info.node = of_node_get(of_graph_get_remote_port(endpoint));
+ if (!info.node)
+ goto error;
+ of_node_put(endpoint);
+
+ lt9711->dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(lt9711->dsi)) {
+ dev_err(dev, "DSI device registration failed: %ld\n",
+ PTR_ERR(lt9711->dsi));
+ return PTR_ERR(lt9711->dsi);
+ }
+
+ INIT_DELAYED_WORK(&lt9711->init_work, init_work_func);
+
+ return 0;
+error:
+ of_node_put(endpoint);
+ return -ENODEV;
+}
+
+static void lt9711_remove(struct i2c_client *client)
+{
+ struct lt9711 *lt9711 = i2c_get_clientdata(client);
+
+ DRM_DEBUG("%s()\n", __func__);
+
+ mipi_dsi_detach(lt9711->dsi);
+
+ drm_panel_remove(&lt9711->base);
+
+ mipi_dsi_device_unregister(lt9711->dsi);
+}
+
+static struct i2c_device_id lt9711_id[] = {
+ { "lontium,lt9711", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, lt9711_id);
+
+static const struct of_device_id lt9711_match_table[] = {
+ { .compatible = "lontium,lt9711" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lt9711_match_table);
+
+static struct i2c_driver lt9711_driver = {
+ .driver = {
+ .name = "lt9711",
+ .of_match_table = lt9711_match_table,
+ },
+ .probe = lt9711_probe,
+ .remove = lt9711_remove,
+ .id_table = lt9711_id,
+};
+
+static int lt9711_dsi_probe(struct mipi_dsi_device *dsi)
+{
+ int ret;
+
+ DRM_DEBUG("%s()\n", __func__);
+
+ dsi->lanes = 4;
+ dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_LPM);
+ dsi->format = MIPI_DSI_FMT_RGB888;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(&dsi->dev, "failed to attach dsi to host\n");
+ mipi_dsi_device_unregister(dsi);
+ }
+
+ return ret;
+}
+
+static const struct of_device_id spacemit_dp_of_match[] = {
+ { .compatible = "spacemit,dp-panel" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spacemit_edp_of_match);
+
+static struct mipi_dsi_driver lt9711_dsi_driver = {
+ .probe = lt9711_dsi_probe,
+ .driver = {
+ .name = IT9711_DSI_DRIVER_NAME,
+ .of_match_table = spacemit_dp_of_match,
+ },
+};
+
+
+static int __init init_lt9711(void)
+{
+ int err;
+
+ DRM_INFO("%s()\n", __func__);
+
+ mipi_dsi_driver_register(&lt9711_dsi_driver);
+ err = i2c_add_driver(&lt9711_driver);
+
+ return err;
+}
+
+module_init(init_lt9711);
+
+static void __exit exit_lt9711(void)
+{
+ DRM_INFO("%s()\n", __func__);
+
+ i2c_del_driver(&lt9711_driver);
+ mipi_dsi_driver_unregister(&lt9711_dsi_driver);
+}
+module_exit(exit_lt9711);
+
+MODULE_DESCRIPTION("LT9711_MIPI to DP Reg Setting driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/spacemit/spacemit_dsi.c b/drivers/gpu/drm/spacemit/spacemit_dsi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/spacemit_dsi.c
+++ b/drivers/gpu/drm/spacemit/spacemit_dsi.c
@@ -462,7 +462,7 @@ static int spacemit_dsi_connector_get_modes(struct drm_connector *connector)
{
struct spacemit_dsi *dsi = connector_to_dsi(connector);
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
return drm_panel_get_modes(dsi->panel, connector);
}
@@ -473,7 +473,7 @@ spacemit_dsi_connector_mode_valid(struct drm_connector *connector,
{
enum drm_mode_status mode_status = MODE_OK;
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
return mode_status;
}
@@ -496,7 +496,7 @@ static struct drm_connector_helper_funcs spacemit_dsi_connector_helper_funcs = {
static enum drm_connector_status
spacemit_dsi_connector_detect(struct drm_connector *connector, bool force)
{
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
return connector_status_connected;
}
@@ -633,7 +633,7 @@ static void spacemit_dsi_unbind(struct device *dev,
struct device *master, void *data)
{
/* do nothing */
- DRM_INFO("%s()\n", __func__);
+ DRM_DEBUG("%s()\n", __func__);
}
diff --git a/drivers/gpu/drm/spacemit/spacemit_hdmi.c b/drivers/gpu/drm/spacemit/spacemit_hdmi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/spacemit/spacemit_hdmi.c
+++ b/drivers/gpu/drm/spacemit/spacemit_hdmi.c
@@ -40,7 +40,7 @@
struct hdmi_data_info {
- uint8_t edid[128];
+ uint8_t edid[EDID_LENGTH];
int vic;
bool sink_has_audio;
unsigned int enc_in_format;
@@ -409,7 +409,7 @@ static void hdmi_i2c_read(struct spacemit_hdmi *hdmi, uint8_t addr, uint8_t* mes
value |= SPACEMIT_HDMI_DDC_DONE;
hdmi_writeb(hdmi, 0xc, value);
- udelay(5);
+ udelay(100);
DRM_DEBUG("hdmi_i2c_read --%u\r\n", length);
@@ -459,6 +459,7 @@ static int hdmi_i2c_write(struct spacemit_hdmi *hdmi, uint8_t addr, uint8_t* mes
DRM_INFO("%s wait hdmi ddc command done timeout\n", __func__);
return -1;
}
+ udelay(100);
DRM_DEBUG("hdmi_i2c_write --%u\r\n", length);
@@ -469,16 +470,26 @@ static int hdmi_i2c_write(struct spacemit_hdmi *hdmi, uint8_t addr, uint8_t* mes
int edid_read (struct spacemit_hdmi *hdmi){
int i;
struct hdmi_data_info *hdmi_data = hdmi->hdmi_data;
+ uint8_t offset;
+ int result;
DRM_DEBUG("%s()\n", __func__);
- if (0 == hdmi_i2c_write(hdmi, 0x50, hdmi_data->edid, 1))
- hdmi_i2c_read(hdmi, 0x50, hdmi_data->edid, EDID_LENGTH);
- else
- return -1;
+ for(i = 0; i < 8; i++) {
+ offset = i * 16;
+ result = hdmi_i2c_write(hdmi, 0x50, &offset, 1);
+ if (result < 0)
+ break;
+ hdmi_i2c_read(hdmi, 0x50, hdmi_data->edid + offset, 16);
+ }
+
+ if (result < 0) {
+ memset(hdmi_data->edid, 0x00, EDID_LENGTH);
+ return result;
+ }
for(i = 0; i < EDID_LENGTH; i += 4){
- DRM_INFO("EDID 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\r\n", i,
+ DRM_DEBUG("EDID 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\r\n", i,
hdmi_data->edid[i], hdmi_data->edid[i+1], hdmi_data->edid[i+2], hdmi_data->edid[i+3]);
}
@@ -565,7 +576,7 @@ void hdmi_init (struct spacemit_hdmi *hdmi, int pixel_clock, int bit_depth){
pll_reg(hdmi, pixel_clock, bit_depth);
writel(0x03, hdmi->regs + 0xe4);
value = readl_relaxed(hdmi->regs + 0xe4);
- DRM_INFO("%s() hdmi pll lock status 0x%x\n", __func__, value);
+ DRM_DEBUG("%s() hdmi pll lock status 0x%x\n", __func__, value);
// while ( (value & 0x10000) != 0) {
// value = readl_relaxed(hdmi->regs + 0xe4);
// }
@@ -691,7 +702,7 @@ spacemit_hdmi_connector_detect(struct drm_connector *connector, bool force)
int ret;
enum drm_connector_status status;
- DRM_INFO("%s() \n", __func__);
+ DRM_DEBUG("%s() \n", __func__);
ret = pm_runtime_get_sync(hdmi->dev);
if (ret < 0) {
@@ -720,13 +731,13 @@ static int spacemit_hdmi_connector_get_modes(struct drm_connector *connector)
struct edid *edid;
uint32_t value;
- DRM_INFO("%s() \n", __func__);
+ DRM_DEBUG("%s() \n", __func__);
if (hdmi->use_no_edid)
return drm_add_modes_noedid(connector, 1920, 1080);
value = hdmi_readb(hdmi, SPACEMIT_HDMI_PHY_STATUS);
- DRM_INFO("%s() hdmi status 0x%x\n", __func__, value);
+ DRM_DEBUG("%s() hdmi status 0x%x\n", __func__, value);
value &= ~(SPACEMIT_HDMI_DDC_OTHER_MASK | SPACEMIT_HDMI_DDC_DONE_MASK);
value |= (SPACEMIT_HDMI_HPD_IQR | SPACEMIT_HDMI_DDC_DONE | SPACEMIT_HDMI_DDC_NACK);
hdmi_writeb(hdmi, SPACEMIT_HDMI_PHY_STATUS, value);
@@ -853,7 +864,7 @@ static int spacemit_hdmi_bind(struct device *dev, struct device *master,
int irq;
int ret;
- DRM_INFO("%s() \n", __func__);
+ DRM_DEBUG("%s() \n", __func__);
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
@@ -932,7 +943,7 @@ static void spacemit_hdmi_unbind(struct device *dev, struct device *master,
struct spacemit_hdmi *hdmi = dev_get_drvdata(dev);
int ret;
- DRM_INFO("%s() \n", __func__);
+ DRM_DEBUG("%s() \n", __func__);
hdmi->connector.funcs->destroy(&hdmi->connector);
hdmi->encoder.funcs->destroy(&hdmi->encoder);
@@ -978,7 +989,7 @@ static int hdmi_rt_pm_resume(struct device *dev)
clk_prepare_enable(hdmi->hdmi_mclk);
clk_val = clk_get_rate(hdmi->hdmi_mclk);
- DRM_INFO("get hdmi mclk=%lld\n", clk_val);
+ DRM_DEBUG("get hdmi mclk=%lld\n", clk_val);
if(clk_val != DPU_MCLK_DEFAULT){
clk_val = clk_round_rate(hdmi->hdmi_mclk, DPU_MCLK_DEFAULT);
clk_set_rate(hdmi->hdmi_mclk, clk_val);
diff --git a/drivers/pci/controller/dwc/pcie-k1x.c b/drivers/pci/controller/dwc/pcie-k1x.c
index 111111111111..222222222222 100644
--- a/drivers/pci/controller/dwc/pcie-k1x.c
+++ b/drivers/pci/controller/dwc/pcie-k1x.c
@@ -263,7 +263,6 @@ void porta_rterm(struct k1x_pcie *k1x)
u32 val;
//REG32(PMUA_REG_BASE + 0x3CC) = 0x4000003f;
- val = k1x_pcie_conf0_reg_readl(k1x, 0);
val = 0x4000003f;
k1x_pcie_conf0_reg_writel(k1x, 0 , val);
@@ -356,15 +355,13 @@ void porta_rterm(struct k1x_pcie *k1x)
k1x_pcie_phy0_reg_writel(k1x, (0x12 << 2), val);
//REG32(0xC0B10000 + (0x02 << 2)) = 0x00000B78; // PU_ADDR_CLK_CFG of lane0
- val = k1x_pcie_phy0_reg_readl(k1x, (0x02 << 2));
val = 0x00000B78;
k1x_pcie_phy0_reg_writel(k1x, (0x02 << 2), val);
//REG32(0xC0B10000 + (0x06 << 2)) = 0x00000400; // force rcv done
- val = k1x_pcie_phy0_reg_readl(k1x, (0x06 << 2));
val = 0x00000400;
k1x_pcie_phy0_reg_writel(k1x, (0x06 << 2), val);
- printk("Now waiting portA resister tuning done...\n");
+ pr_debug("Now waiting portA resister tuning done...\n");
// force PCIE mpu_u3/pu_rx_lfps
//REG32(PCIE_PUPHY_REG_BASE + 0x6 * 4) |= (0x1 << 17) | (0x1 << 15);
@@ -379,7 +376,7 @@ void porta_rterm(struct k1x_pcie *k1x)
//rd_data = REG32(0xC0B10000 + 0x21 * 4);
rd_data = k1x_pcie_phy0_reg_readl(k1x, (0x21 * 4));
if (count++ > 5000) {
- printk(KERN_WARNING "read pcie0 phy rd_data time out.\n");
+ pr_err("read pcie0 phy rd_data time out.\n");
break;
}
} while (((rd_data >> 10) & 0x1) == 0); // waiting PCIe portA readonly_reg2[2] r_tune_done==1
@@ -392,8 +389,8 @@ void rterm_force(struct k1x_pcie *k1x, u32 pcie_rcal)
u32 val = 0;
lane = k1x->num_lanes;
- printk("pcie_rcal = 0x%08x\n", pcie_rcal);
- printk("pcie port id = %d, lane num = %d\n", k1x->port_id, lane);
+ pr_debug("pcie_rcal = 0x%08x\n", pcie_rcal);
+ pr_debug("pcie port id = %d, lane num = %d\n", k1x->port_id, lane);
// 2.write pma0 rterm value LSB[3:0](read0nly1[3:0]) to lane0/1 rx_reg1
for (i = 0; i < lane; i++)
@@ -476,8 +473,8 @@ static int init_phy(struct k1x_pcie *k1x)
u32 val = 0;
int count;
- printk("Now init Rterm...\n");
- printk("pcie prot id = %d, porta_init_done = %d\n", k1x->port_id, porta_init_done);
+ pr_debug("Now init Rterm...\n");
+ pr_debug("pcie prot id = %d, porta_init_done = %d\n", k1x->port_id, porta_init_done);
if (k1x->port_id != 0) {
if (porta_init_done == 0) {
porta_rterm(k1x);
@@ -498,7 +495,7 @@ static int init_phy(struct k1x_pcie *k1x)
//rd_data = REG32(0xC0B10000 + 0x21 * 4);
rd_data = k1x_pcie_phy0_reg_readl(k1x, (0x21 * 4));
if (count++ > 5000) {
- printk(KERN_WARNING "read pcie0 phy rd_data time out.\n");
+ pr_err("read pcie0 phy rd_data time out.\n");
break;
}
} while (((rd_data >> 10) & 0x1) == 0);
@@ -509,7 +506,7 @@ static int init_phy(struct k1x_pcie *k1x)
k1x->pcie_rcal = pcie_rcal;
rterm_force(k1x, pcie_rcal);
- printk("Now int init_puphy...\n");
+ pr_debug("Now int init_puphy...\n");
val = k1x_pcie_readl(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD);
val &= 0xbfffffff;
k1x_pcie_writel(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD, val);
@@ -579,40 +576,32 @@ static int init_phy(struct k1x_pcie *k1x)
k1x_pcie_phy_reg_writel(k1x, (0x12 << 2), val);
// PU_ADDR_CLK_CFG of lane0
- val = k1x_pcie_phy_reg_readl(k1x, (0x02 << 2));
val = 0x00000B78;
k1x_pcie_phy_reg_writel(k1x, (0x02 << 2), val);
// PU_ADDR_CLK_CFG of lane1
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x02 << 2));
val = 0x00000B78;
k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x02 << 2), val);
// force rcv done
- val = k1x_pcie_phy_reg_readl(k1x, (0x06 << 2));
val = 0x00000400;
k1x_pcie_phy_reg_writel(k1x, (0x06 << 2), val);
- // force rcv done
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x06 << 2));
- val = 0x00000400;
- k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x06 << 2), val);
-
// waiting pll lock
- printk("waiting pll lock...\n");
+ pr_debug("waiting pll lock...\n");
count = 0;
do
{
rd_data = k1x_pcie_phy_reg_readl(k1x, 0x8);
if (count++ > 5000) {
- printk(KERN_WARNING "read pcie%d phy rd_data time out.\n", k1x->port_id);
+ pr_err("read pcie%d phy rd_data time out.\n", k1x->port_id);
break;
}
} while ((rd_data & 0x1) == 0);
if (k1x->port_id == 0)
porta_init_done = 0x1;
- printk("Now finish init_puphy....\n");
+ pr_debug("Now finish init_puphy....\n");
return 0;
}
@@ -669,7 +658,7 @@ static int k1x_pcie_establish_link(struct dw_pcie *pci)
reg &= ~APP_HOLD_PHY_RST;
k1x_pcie_writel(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD, reg);
- printk("ltssm enable\n");
+ pr_debug("ltssm enable\n");
return 0;
}
@@ -864,7 +853,7 @@ void k1x_pcie_msix_addr_alloc(struct dw_pcie_rp *pp)
}
msi_target = (u64)k1x->msix_addr;
- pr_info("(u64)pp->msix_addr =%llx\n", (u64)k1x->msix_addr);
+ pr_debug("(u64)pp->msix_addr =%llx\n", (u64)k1x->msix_addr);
reg = k1x_pcie_phy_ahb_readl(k1x, ADDR_MSI_RECV_CTRL);
reg |= MSIX_MON_EN;
k1x_pcie_phy_ahb_writel(k1x, ADDR_MSI_RECV_CTRL, reg);
@@ -893,7 +882,7 @@ void k1x_pcie_msi_addr_alloc(struct dw_pcie_rp *pp)
}
msi_target = (u64)pp->msi_data;
- pr_info("(u64)pp->msi_data =%llx\n", (u64)pp->msi_data);
+ pr_debug("(u64)pp->msi_data =%llx\n", (u64)pp->msi_data);
/* Program the msi_data */
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
@@ -1017,7 +1006,7 @@ static int k1x_pcie_host_init(struct dw_pcie_rp *pp)
/* read the link status register, get the current speed */
reg = dw_pcie_readw_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKSTA);
- pr_info("Link up, Gen%i\n", reg & PCI_EXP_LNKSTA_CLS);
+ pr_debug("Link up, Gen%i\n", reg & PCI_EXP_LNKSTA_CLS);
k1x_pcie_enable_msi_interrupts(k1x);
@@ -1396,7 +1385,7 @@ static int k1x_pcie_enable_phy(struct k1x_pcie *k1x)
u32 reg, val, rd_data;
int count;
- printk("Now k1x_pcie_enable_phy in resume...\n");
+ pr_debug("Now k1x_pcie_enable_phy in resume...\n");
reg = k1x_pcie_readl(k1x, PCIECTRL_K1X_CONF_DEVICE_CMD);
reg |= 0x3f;
@@ -1473,38 +1462,30 @@ static int k1x_pcie_enable_phy(struct k1x_pcie *k1x)
k1x_pcie_phy_reg_writel(k1x, (0x12 << 2), val);
// PU_ADDR_CLK_CFG of lane0
- val = k1x_pcie_phy_reg_readl(k1x, (0x02 << 2));
val = 0x00000B78;
k1x_pcie_phy_reg_writel(k1x, (0x02 << 2), val);
// PU_ADDR_CLK_CFG of lane1
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x02 << 2));
val = 0x00000B78;
k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x02 << 2), val);
// force rcv done
- val = k1x_pcie_phy_reg_readl(k1x, (0x06 << 2));
val = 0x00000400;
k1x_pcie_phy_reg_writel(k1x, (0x06 << 2), val);
- // force rcv done
- val = k1x_pcie_phy_reg_readl(k1x, 0x400 + (0x06 << 2));
- val = 0x00000400;
- k1x_pcie_phy_reg_writel(k1x, 0x400 + (0x06 << 2), val);
-
// waiting pll lock
- printk("waiting pll lock...\n");
+ pr_debug("waiting pll lock...\n");
count = 0;
do
{
rd_data = k1x_pcie_phy_reg_readl(k1x, 0x8);
if (count++ > 5000) {
- printk(KERN_WARNING "read pcie%d phy rd_data time out.\n", k1x->port_id);
+ pr_err("read pcie%d phy rd_data time out.\n", k1x->port_id);
break;
}
} while ((rd_data & 0x1) == 0);
- printk("Now finish enable phy....\n");
+ pr_debug("Now finish enable phy....\n");
return 0;
}
diff --git a/drivers/regulator/spacemit-regulator.c b/drivers/regulator/spacemit-regulator.c
index 111111111111..222222222222 100644
--- a/drivers/regulator/spacemit-regulator.c
+++ b/drivers/regulator/spacemit-regulator.c
@@ -17,6 +17,31 @@
#include <linux/gpio/consumer.h>
#include <linux/mfd/spacemit/spacemit_pmic.h>
+static struct regulator_match_data *match_data;
+
+static int spacemit_regulator_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+ unsigned int reg;
+
+ int sel = regulator_map_voltage_linear_range(rdev, uV, uV);
+
+ if (sel < 0)
+ return -EINVAL;
+
+ /* means that we will disable this vol in suspend */
+ if (uV == rdev->constraints->max_uV)
+ /* BUCK will set 0xff to close the power */
+ sel = rdev->desc->vsel_mask;
+ else if (uV == rdev->constraints->min_uV)
+ /* LDO will set zero to close the power */
+ sel = 0;
+
+ reg = rdev->desc->vsel_reg + match_data->sleep_reg_offset;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->vsel_mask, sel);
+}
+
static const struct regulator_ops pmic_dcdc_ldo_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
@@ -26,6 +51,7 @@ static const struct regulator_ops pmic_dcdc_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_voltage = spacemit_regulator_set_suspend_voltage,
};
static const struct regulator_ops pmic_switch_ops = {
@@ -57,7 +83,6 @@ static int spacemit_regulator_probe(struct platform_device *pdev)
struct spacemit_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
struct i2c_client *client;
const struct of_device_id *of_id;
- struct regulator_match_data *match_data;
struct regulator_dev *regulator_dev;
int i;
diff --git a/drivers/remoteproc/k1x-rproc.c b/drivers/remoteproc/k1x-rproc.c
index 111111111111..222222222222 100644
--- a/drivers/remoteproc/k1x-rproc.c
+++ b/drivers/remoteproc/k1x-rproc.c
@@ -619,12 +619,16 @@ static int spacemit_rproc_probe(struct platform_device *pdev)
register_platform_pm_ops(&rproc_platform_pm_ops);
#endif
- rproc->auto_boot = true;
ret = devm_rproc_add(dev, rproc);
if (ret) {
dev_err(dev, "rproc_add failed\n");
}
+ ret = rproc_boot(rproc);
+ if (ret) {
+ dev_err(dev, "rproc_boot failed\n");
+ }
+
return ret;
}
@@ -656,6 +660,7 @@ static int spacemit_rproc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
unregister_rpmsg_driver(&rpmsg_rcpu_pm_client);
+ unregister_platform_pm_ops(&rproc_platform_pm_ops);
#endif
return 0;
}
@@ -700,7 +705,7 @@ static __init int spacemit_rproc_driver_init(void)
{
return platform_driver_register(&spacemit_rproc_driver);
}
-subsys_initcall(spacemit_rproc_driver_init);
+device_initcall(spacemit_rproc_driver_init);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("sapcemit remote processor control driver");
diff --git a/drivers/soc/spacemit/jpu/jpu.c b/drivers/soc/spacemit/jpu/jpu.c
index 111111111111..222222222222 100644
--- a/drivers/soc/spacemit/jpu/jpu.c
+++ b/drivers/soc/spacemit/jpu/jpu.c
@@ -1695,7 +1695,7 @@ static int jpu_probe(struct platform_device *pdev)
cpuid = 0;
cpumask_set_cpu(cpuid, &mask);
irq_set_affinity(jdev->s_jpu_irq, &mask);
- dev_notice(jdev->jdev, "driver probe successfully\n");
+ dev_dbg(jdev->jdev, "driver probe successfully\n");
return 0;
err0:
return -1;
@@ -1730,7 +1730,7 @@ static int jpu_remove(struct platform_device *pdev)
#endif
sysfs_remove_groups(&pdev->dev.kobj, jpu_frequency_group);
- dev_notice(jdev->jdev, "driver removed\n");
+ dev_dbg(jdev->jdev, "driver removed\n");
return 0;
}
diff --git a/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c b/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
index 111111111111..222222222222 100644
--- a/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
+++ b/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
@@ -473,8 +473,9 @@ static void spacemit_pd_detach_dev(struct generic_pm_domain *genpd, struct devic
dev_pm_qos_remove_notifier(dev, &pos->notifier, DEV_PM_QOS_MAX_FREQUENCY);
while (--pos->rgr_count >= 0)
devm_regulator_put(pos->rgr[pos->rgr_count]);
- list_del(&pos->qos_node);
}
+
+ list_del(&pos->qos_node);
}
static int spacemit_cpuidle_qos_notfier_call(struct notifier_block *nb, unsigned long action, void *data)
diff --git a/drivers/spi/spi-k1x-qspi.c b/drivers/spi/spi-k1x-qspi.c
index 111111111111..222222222222 100644
--- a/drivers/spi/spi-k1x-qspi.c
+++ b/drivers/spi/spi-k1x-qspi.c
@@ -1305,8 +1305,11 @@ static int k1x_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
if (op->data.nbytes > qspi->tx_unit_size)
op->data.nbytes = qspi->tx_unit_size;
} else {
- if (op->data.nbytes > qspi->rx_unit_size)
+ if (op->data.nbytes > qspi->rx_unit_size) {
op->data.nbytes = qspi->rx_unit_size;
+ } else if (op->data.nbytes > qspi->rx_buf_size - 4 && !IS_ALIGNED(op->data.nbytes, 4)) {
+ op->data.nbytes = qspi->rx_buf_size - 4;
+ }
}
mutex_unlock(&qspi->lock);
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 111111111111..222222222222 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -547,6 +547,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity);
DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment);
DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
#define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \
static ssize_t _name##_store(struct config_item *item, const char *page,\
@@ -1186,6 +1187,23 @@ static ssize_t pgr_support_store(struct config_item *item,
return count;
}
+static ssize_t emulate_rsoc_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct se_dev_attrib *da = to_attrib(item);
+ bool flag;
+ int ret;
+
+ ret = strtobool(page, &flag);
+ if (ret < 0)
+ return ret;
+
+ da->emulate_rsoc = flag;
+ pr_debug("dev[%p]: SE Device REPORT_SUPPORTED_OPERATION_CODES_EMULATION flag: %d\n",
+ da->da_dev, flag);
+ return count;
+}
+
CONFIGFS_ATTR(, emulate_model_alias);
CONFIGFS_ATTR(, emulate_dpo);
CONFIGFS_ATTR(, emulate_fua_write);
@@ -1198,6 +1216,7 @@ CONFIGFS_ATTR(, emulate_tpws);
CONFIGFS_ATTR(, emulate_caw);
CONFIGFS_ATTR(, emulate_3pc);
CONFIGFS_ATTR(, emulate_pr);
+CONFIGFS_ATTR(, emulate_rsoc);
CONFIGFS_ATTR(, pi_prot_type);
CONFIGFS_ATTR_RO(, hw_pi_prot_type);
CONFIGFS_ATTR(, pi_prot_format);
@@ -1261,6 +1280,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
&attr_max_write_same_len,
&attr_alua_support,
&attr_pgr_support,
+ &attr_emulate_rsoc,
NULL,
};
EXPORT_SYMBOL(sbc_attrib_attrs);
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 111111111111..222222222222 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1314,6 +1314,922 @@ spc_emulate_testunitready(struct se_cmd *cmd)
return 0;
}
+static void set_dpofua_usage_bits(u8 *usage_bits, struct se_device *dev)
+{
+ if (!target_check_fua(dev))
+ usage_bits[1] &= ~0x18;
+ else
+ usage_bits[1] |= 0x18;
+}
+
+static void set_dpofua_usage_bits32(u8 *usage_bits, struct se_device *dev)
+{
+ if (!target_check_fua(dev))
+ usage_bits[10] &= ~0x18;
+ else
+ usage_bits[10] |= 0x18;
+}
+
+static struct target_opcode_descriptor tcm_opcode_read6 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = READ_6,
+ .cdb_size = 6,
+ .usage_bits = {READ_6, 0x1f, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_read10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = READ_10,
+ .cdb_size = 10,
+ .usage_bits = {READ_10, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_read12 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = READ_12,
+ .cdb_size = 12,
+ .usage_bits = {READ_12, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_read16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = READ_16,
+ .cdb_size = 16,
+ .usage_bits = {READ_16, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write6 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_6,
+ .cdb_size = 6,
+ .usage_bits = {WRITE_6, 0x1f, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_write10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_10,
+ .cdb_size = 10,
+ .usage_bits = {WRITE_10, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write_verify10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_VERIFY,
+ .cdb_size = 10,
+ .usage_bits = {WRITE_VERIFY, 0xf0, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write12 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_12,
+ .cdb_size = 12,
+ .usage_bits = {WRITE_12, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_16,
+ .cdb_size = 16,
+ .usage_bits = {WRITE_16, 0xf8, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write_verify16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_VERIFY_16,
+ .cdb_size = 16,
+ .usage_bits = {WRITE_VERIFY_16, 0xf0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static bool tcm_is_ws_enabled(struct se_cmd *cmd)
+{
+ struct sbc_ops *ops = cmd->protocol_data;
+ struct se_device *dev = cmd->se_dev;
+
+ return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) ||
+ !!ops->execute_write_same;
+}
+
+static struct target_opcode_descriptor tcm_opcode_write_same32 = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = VARIABLE_LENGTH_CMD,
+ .service_action = WRITE_SAME_32,
+ .cdb_size = 32,
+ .usage_bits = {VARIABLE_LENGTH_CMD, SCSI_CONTROL_MASK, 0x00, 0x00,
+ 0x00, 0x00, SCSI_GROUP_NUMBER_MASK, 0x18,
+ 0x00, WRITE_SAME_32, 0xe8, 0x00,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff},
+ .enabled = tcm_is_ws_enabled,
+ .update_usage_bits = set_dpofua_usage_bits32,
+};
+
+static bool tcm_is_caw_enabled(struct se_cmd *cmd)
+{
+ struct se_device *dev = cmd->se_dev;
+
+ return dev->dev_attrib.emulate_caw;
+}
+
+static struct target_opcode_descriptor tcm_opcode_compare_write = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = COMPARE_AND_WRITE,
+ .cdb_size = 16,
+ .usage_bits = {COMPARE_AND_WRITE, 0x18, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_caw_enabled,
+ .update_usage_bits = set_dpofua_usage_bits,
+};
+
+static struct target_opcode_descriptor tcm_opcode_read_capacity = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = READ_CAPACITY,
+ .cdb_size = 10,
+ .usage_bits = {READ_CAPACITY, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00,
+ 0x01, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_read_capacity16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = SERVICE_ACTION_IN_16,
+ .service_action = SAI_READ_CAPACITY_16,
+ .cdb_size = 16,
+ .usage_bits = {SERVICE_ACTION_IN_16, SAI_READ_CAPACITY_16, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+};
+
+static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd)
+{
+ struct se_device *dev = cmd->se_dev;
+
+ spin_lock(&dev->t10_alua.lba_map_lock);
+ if (list_empty(&dev->t10_alua.lba_map_list)) {
+ spin_unlock(&dev->t10_alua.lba_map_lock);
+ return false;
+ }
+ spin_unlock(&dev->t10_alua.lba_map_lock);
+ return true;
+
+}
+
+static struct target_opcode_descriptor tcm_opcode_read_report_refferals = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = SERVICE_ACTION_IN_16,
+ .service_action = SAI_REPORT_REFERRALS,
+ .cdb_size = 16,
+ .usage_bits = {SERVICE_ACTION_IN_16, SAI_REPORT_REFERRALS, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_rep_ref_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_sync_cache = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = SYNCHRONIZE_CACHE,
+ .cdb_size = 10,
+ .usage_bits = {SYNCHRONIZE_CACHE, 0x02, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_sync_cache16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = SYNCHRONIZE_CACHE_16,
+ .cdb_size = 16,
+ .usage_bits = {SYNCHRONIZE_CACHE_16, 0x02, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+};
+
+static bool tcm_is_unmap_enabled(struct se_cmd *cmd)
+{
+ struct sbc_ops *ops = cmd->protocol_data;
+ struct se_device *dev = cmd->se_dev;
+
+ return ops->execute_unmap && dev->dev_attrib.emulate_tpu;
+}
+
+static struct target_opcode_descriptor tcm_opcode_unmap = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = UNMAP,
+ .cdb_size = 10,
+ .usage_bits = {UNMAP, 0x00, 0x00, 0x00,
+ 0x00, 0x00, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_unmap_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write_same = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_SAME,
+ .cdb_size = 10,
+ .usage_bits = {WRITE_SAME, 0xe8, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_ws_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_write_same16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = WRITE_SAME_16,
+ .cdb_size = 16,
+ .usage_bits = {WRITE_SAME_16, 0xe8, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_ws_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_verify = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = VERIFY,
+ .cdb_size = 10,
+ .usage_bits = {VERIFY, 0x00, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_verify16 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = VERIFY_16,
+ .cdb_size = 16,
+ .usage_bits = {VERIFY_16, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_start_stop = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = START_STOP,
+ .cdb_size = 6,
+ .usage_bits = {START_STOP, 0x01, 0x00, 0x00,
+ 0x01, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_mode_select = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = MODE_SELECT,
+ .cdb_size = 6,
+ .usage_bits = {MODE_SELECT, 0x10, 0x00, 0x00,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_mode_select10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = MODE_SELECT_10,
+ .cdb_size = 10,
+ .usage_bits = {MODE_SELECT_10, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_mode_sense = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = MODE_SENSE,
+ .cdb_size = 6,
+ .usage_bits = {MODE_SENSE, 0x08, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_mode_sense10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = MODE_SENSE_10,
+ .cdb_size = 10,
+ .usage_bits = {MODE_SENSE_10, 0x18, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_pri_read_keys = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_IN,
+ .service_action = PRI_READ_KEYS,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_KEYS, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_IN,
+ .service_action = PRI_READ_RESERVATION,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_RESERVATION, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static bool tcm_is_pr_enabled(struct se_cmd *cmd)
+{
+ struct se_device *dev = cmd->se_dev;
+
+ return dev->dev_attrib.emulate_pr;
+}
+
+static struct target_opcode_descriptor tcm_opcode_pri_read_caps = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_IN,
+ .service_action = PRI_REPORT_CAPABILITIES,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_REPORT_CAPABILITIES, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pri_read_full_status = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_IN,
+ .service_action = PRI_READ_FULL_STATUS,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_FULL_STATUS, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_register = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_REGISTER,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_REGISTER, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_reserve = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_RESERVE,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_RESERVE, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_release = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_RELEASE,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_RELEASE, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_clear = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_CLEAR,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_CLEAR, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_preempt = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_PREEMPT,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_PREEMPT, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_PREEMPT_AND_ABORT,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_PREEMPT_AND_ABORT, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_REGISTER_AND_IGNORE_EXISTING_KEY,
+ .cdb_size = 10,
+ .usage_bits = {
+ PERSISTENT_RESERVE_OUT, PRO_REGISTER_AND_IGNORE_EXISTING_KEY,
+ 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_pro_register_move = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = PERSISTENT_RESERVE_OUT,
+ .service_action = PRO_REGISTER_AND_MOVE,
+ .cdb_size = 10,
+ .usage_bits = {PERSISTENT_RESERVE_OUT, PRO_REGISTER_AND_MOVE, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_pr_enabled,
+};
+
+static bool tcm_is_scsi2_reservations_enabled(struct se_cmd *cmd)
+{
+ struct se_device *dev = cmd->se_dev;
+
+ return dev->dev_attrib.emulate_pr;
+}
+
+static struct target_opcode_descriptor tcm_opcode_release = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = RELEASE,
+ .cdb_size = 6,
+ .usage_bits = {RELEASE, 0x00, 0x00, 0x00,
+ 0x00, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_scsi2_reservations_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_release10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = RELEASE_10,
+ .cdb_size = 10,
+ .usage_bits = {RELEASE_10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_scsi2_reservations_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_reserve = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = RESERVE,
+ .cdb_size = 6,
+ .usage_bits = {RESERVE, 0x00, 0x00, 0x00,
+ 0x00, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_scsi2_reservations_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_reserve10 = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = RESERVE_10,
+ .cdb_size = 10,
+ .usage_bits = {RESERVE_10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_scsi2_reservations_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_request_sense = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = REQUEST_SENSE,
+ .cdb_size = 6,
+ .usage_bits = {REQUEST_SENSE, 0x00, 0x00, 0x00,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_inquiry = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = INQUIRY,
+ .cdb_size = 6,
+ .usage_bits = {INQUIRY, 0x01, 0xff, 0xff,
+ 0xff, SCSI_CONTROL_MASK},
+};
+
+static bool tcm_is_3pc_enabled(struct se_cmd *cmd)
+{
+ struct se_device *dev = cmd->se_dev;
+
+ return dev->dev_attrib.emulate_3pc;
+}
+
+static struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = EXTENDED_COPY,
+ .cdb_size = 16,
+ .usage_bits = {EXTENDED_COPY, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_3pc_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = RECEIVE_COPY_RESULTS,
+ .service_action = RCR_SA_OPERATING_PARAMETERS,
+ .cdb_size = 16,
+ .usage_bits = {RECEIVE_COPY_RESULTS, RCR_SA_OPERATING_PARAMETERS,
+ 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_3pc_enabled,
+};
+
+static struct target_opcode_descriptor tcm_opcode_report_luns = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = REPORT_LUNS,
+ .cdb_size = 12,
+ .usage_bits = {REPORT_LUNS, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_test_unit_ready = {
+ .support = SCSI_SUPPORT_FULL,
+ .opcode = TEST_UNIT_READY,
+ .cdb_size = 6,
+ .usage_bits = {TEST_UNIT_READY, 0x00, 0x00, 0x00,
+ 0x00, SCSI_CONTROL_MASK},
+};
+
+static struct target_opcode_descriptor tcm_opcode_report_target_pgs = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = MAINTENANCE_IN,
+ .service_action = MI_REPORT_TARGET_PGS,
+ .cdb_size = 12,
+ .usage_bits = {MAINTENANCE_IN, 0xE0 | MI_REPORT_TARGET_PGS, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+};
+
+
+static bool spc_rsoc_enabled(struct se_cmd *cmd)
+{
+ struct se_device *dev = cmd->se_dev;
+
+ return dev->dev_attrib.emulate_rsoc;
+}
+
+static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = MAINTENANCE_IN,
+ .service_action = MI_REPORT_SUPPORTED_OPERATION_CODES,
+ .cdb_size = 12,
+ .usage_bits = {MAINTENANCE_IN, MI_REPORT_SUPPORTED_OPERATION_CODES,
+ 0x87, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+ .enabled = spc_rsoc_enabled,
+};
+
+static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd)
+{
+ struct t10_alua_tg_pt_gp *l_tg_pt_gp;
+ struct se_lun *l_lun = cmd->se_lun;
+
+ rcu_read_lock();
+ l_tg_pt_gp = rcu_dereference(l_lun->lun_tg_pt_gp);
+ if (!l_tg_pt_gp) {
+ rcu_read_unlock();
+ return false;
+ }
+ if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
+ rcu_read_unlock();
+ return false;
+ }
+ rcu_read_unlock();
+
+ return true;
+}
+
+static struct target_opcode_descriptor tcm_opcode_set_tpg = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = MAINTENANCE_OUT,
+ .service_action = MO_SET_TARGET_PGS,
+ .cdb_size = 12,
+ .usage_bits = {MAINTENANCE_OUT, MO_SET_TARGET_PGS, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+ .enabled = tcm_is_set_tpg_enabled,
+};
+
+static struct target_opcode_descriptor *tcm_supported_opcodes[] = {
+ &tcm_opcode_read6,
+ &tcm_opcode_read10,
+ &tcm_opcode_read12,
+ &tcm_opcode_read16,
+ &tcm_opcode_write6,
+ &tcm_opcode_write10,
+ &tcm_opcode_write_verify10,
+ &tcm_opcode_write12,
+ &tcm_opcode_write16,
+ &tcm_opcode_write_verify16,
+ &tcm_opcode_write_same32,
+ &tcm_opcode_compare_write,
+ &tcm_opcode_read_capacity,
+ &tcm_opcode_read_capacity16,
+ &tcm_opcode_read_report_refferals,
+ &tcm_opcode_sync_cache,
+ &tcm_opcode_sync_cache16,
+ &tcm_opcode_unmap,
+ &tcm_opcode_write_same,
+ &tcm_opcode_write_same16,
+ &tcm_opcode_verify,
+ &tcm_opcode_verify16,
+ &tcm_opcode_start_stop,
+ &tcm_opcode_mode_select,
+ &tcm_opcode_mode_select10,
+ &tcm_opcode_mode_sense,
+ &tcm_opcode_mode_sense10,
+ &tcm_opcode_pri_read_keys,
+ &tcm_opcode_pri_read_resrv,
+ &tcm_opcode_pri_read_caps,
+ &tcm_opcode_pri_read_full_status,
+ &tcm_opcode_pro_register,
+ &tcm_opcode_pro_reserve,
+ &tcm_opcode_pro_release,
+ &tcm_opcode_pro_clear,
+ &tcm_opcode_pro_preempt,
+ &tcm_opcode_pro_preempt_abort,
+ &tcm_opcode_pro_reg_ign_exist,
+ &tcm_opcode_pro_register_move,
+ &tcm_opcode_release,
+ &tcm_opcode_release10,
+ &tcm_opcode_reserve,
+ &tcm_opcode_reserve10,
+ &tcm_opcode_request_sense,
+ &tcm_opcode_inquiry,
+ &tcm_opcode_extended_copy_lid1,
+ &tcm_opcode_rcv_copy_res_op_params,
+ &tcm_opcode_report_luns,
+ &tcm_opcode_test_unit_ready,
+ &tcm_opcode_report_target_pgs,
+ &tcm_opcode_report_supp_opcodes,
+ &tcm_opcode_set_tpg,
+};
+
+static int
+spc_rsoc_encode_command_timeouts_descriptor(unsigned char *buf, u8 ctdp,
+ struct target_opcode_descriptor *descr)
+{
+ if (!ctdp)
+ return 0;
+
+ put_unaligned_be16(0xa, buf);
+ buf[3] = descr->specific_timeout;
+ put_unaligned_be32(descr->nominal_timeout, &buf[4]);
+ put_unaligned_be32(descr->recommended_timeout, &buf[8]);
+
+ return 12;
+}
+
+static int
+spc_rsoc_encode_command_descriptor(unsigned char *buf, u8 ctdp,
+ struct target_opcode_descriptor *descr)
+{
+ int td_size = 0;
+
+ buf[0] = descr->opcode;
+
+ put_unaligned_be16(descr->service_action, &buf[2]);
+
+ buf[5] = (ctdp << 1) | descr->serv_action_valid;
+ put_unaligned_be16(descr->cdb_size, &buf[6]);
+
+ td_size = spc_rsoc_encode_command_timeouts_descriptor(&buf[8], ctdp,
+ descr);
+
+ return 8 + td_size;
+}
+
+static int
+spc_rsoc_encode_one_command_descriptor(unsigned char *buf, u8 ctdp,
+ struct target_opcode_descriptor *descr,
+ struct se_device *dev)
+{
+ int td_size = 0;
+
+ if (!descr) {
+ buf[1] = (ctdp << 7) | SCSI_SUPPORT_NOT_SUPPORTED;
+ return 2;
+ }
+
+ buf[1] = (ctdp << 7) | SCSI_SUPPORT_FULL;
+ put_unaligned_be16(descr->cdb_size, &buf[2]);
+ memcpy(&buf[4], descr->usage_bits, descr->cdb_size);
+ if (descr->update_usage_bits)
+ descr->update_usage_bits(&buf[4], dev);
+
+ td_size = spc_rsoc_encode_command_timeouts_descriptor(
+ &buf[4 + descr->cdb_size], ctdp, descr);
+
+ return 4 + descr->cdb_size + td_size;
+}
+
+static sense_reason_t
+spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
+{
+ struct target_opcode_descriptor *descr;
+ struct se_session *sess = cmd->se_sess;
+ unsigned char *cdb = cmd->t_task_cdb;
+ u8 opts = cdb[2] & 0x3;
+ u8 requested_opcode;
+ u16 requested_sa;
+ int i;
+
+ requested_opcode = cdb[3];
+ requested_sa = ((u16)cdb[4]) << 8 | cdb[5];
+ *opcode = NULL;
+
+ if (opts > 3) {
+ pr_debug("TARGET_CORE[%s]: Invalid REPORT SUPPORTED OPERATION CODES"
+ " with unsupported REPORTING OPTIONS %#x for 0x%08llx from %s\n",
+ cmd->se_tfo->fabric_name, opts,
+ cmd->se_lun->unpacked_lun,
+ sess->se_node_acl->initiatorname);
+ return TCM_INVALID_CDB_FIELD;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) {
+ descr = tcm_supported_opcodes[i];
+ if (descr->opcode != requested_opcode)
+ continue;
+
+ switch (opts) {
+ case 0x1:
+ /*
+ * If the REQUESTED OPERATION CODE field specifies an
+ * operation code for which the device server implements
+ * service actions, then the device server shall
+ * terminate the command with CHECK CONDITION status,
+ * with the sense key set to ILLEGAL REQUEST, and the
+ * additional sense code set to INVALID FIELD IN CDB
+ */
+ if (descr->serv_action_valid)
+ return TCM_INVALID_CDB_FIELD;
+
+ if (!descr->enabled || descr->enabled(cmd))
+ *opcode = descr;
+ break;
+ case 0x2:
+ /*
+ * If the REQUESTED OPERATION CODE field specifies an
+ * operation code for which the device server does not
+ * implement service actions, then the device server
+ * shall terminate the command with CHECK CONDITION
+ * status, with the sense key set to ILLEGAL REQUEST,
+ * and the additional sense code set to INVALID FIELD IN CDB.
+ */
+ if (descr->serv_action_valid &&
+ descr->service_action == requested_sa) {
+ if (!descr->enabled || descr->enabled(cmd))
+ *opcode = descr;
+ } else if (!descr->serv_action_valid)
+ return TCM_INVALID_CDB_FIELD;
+ break;
+ case 0x3:
+ /*
+ * The command support data for the operation code and
+ * service action a specified in the REQUESTED OPERATION
+ * CODE field and REQUESTED SERVICE ACTION field shall
+ * be returned in the one_command parameter data format.
+ */
+ if (descr->service_action == requested_sa)
+ if (!descr->enabled || descr->enabled(cmd))
+ *opcode = descr;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static sense_reason_t
+spc_emulate_report_supp_op_codes(struct se_cmd *cmd)
+{
+ int descr_num = ARRAY_SIZE(tcm_supported_opcodes);
+ struct target_opcode_descriptor *descr = NULL;
+ unsigned char *cdb = cmd->t_task_cdb;
+ u8 rctd = (cdb[2] >> 7) & 0x1;
+ unsigned char *buf = NULL;
+ int response_length = 0;
+ u8 opts = cdb[2] & 0x3;
+ unsigned char *rbuf;
+ sense_reason_t ret = 0;
+ int i;
+
+ if (!cmd->se_dev->dev_attrib.emulate_rsoc)
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+
+ rbuf = transport_kmap_data_sg(cmd);
+ if (cmd->data_length && !rbuf) {
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ goto out;
+ }
+
+ if (opts == 0)
+ response_length = 4 + (8 + rctd * 12) * descr_num;
+ else {
+ ret = spc_rsoc_get_descr(cmd, &descr);
+ if (ret)
+ goto out;
+
+ if (descr)
+ response_length = 4 + descr->cdb_size + rctd * 12;
+ else
+ response_length = 2;
+ }
+
+ buf = kzalloc(response_length, GFP_KERNEL);
+ if (!buf) {
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ goto out;
+ }
+ response_length = 0;
+
+ if (opts == 0) {
+ response_length += 4;
+
+ for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) {
+ descr = tcm_supported_opcodes[i];
+ if (descr->enabled && !descr->enabled(cmd))
+ continue;
+
+ response_length += spc_rsoc_encode_command_descriptor(
+ &buf[response_length], rctd, descr);
+ }
+ put_unaligned_be32(response_length - 3, buf);
+ } else {
+ response_length = spc_rsoc_encode_one_command_descriptor(
+ &buf[response_length], rctd, descr,
+ cmd->se_dev);
+ }
+
+ memcpy(rbuf, buf, min_t(u32, response_length, cmd->data_length));
+out:
+ kfree(buf);
+ transport_kunmap_data_sg(cmd);
+
+ if (!ret)
+ target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, response_length);
+ return ret;
+}
+
sense_reason_t
spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
{
@@ -1439,6 +2355,10 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
cmd->execute_cmd =
target_emulate_report_target_port_groups;
}
+ if ((cdb[1] & 0x1f) ==
+ MI_REPORT_SUPPORTED_OPERATION_CODES)
+ cmd->execute_cmd =
+ spc_emulate_report_supp_op_codes;
*size = get_unaligned_be32(&cdb[6]);
} else {
/*
diff --git a/drivers/tty/serial/pxa_k1x.c b/drivers/tty/serial/pxa_k1x.c
index 111111111111..222222222222 100644
--- a/drivers/tty/serial/pxa_k1x.c
+++ b/drivers/tty/serial/pxa_k1x.c
@@ -2075,7 +2075,7 @@ static int serial_pxa_probe_dt(struct platform_device *pdev, struct uart_pxa_por
#ifdef CONFIG_PM
if (of_property_read_u32(np, "edge-wakeup-pin", &sport->edge_wakeup_gpio)) {
- dev_info(&pdev->dev, "no edge-wakeup-pin defined\n");
+ dev_dbg(&pdev->dev, "no edge-wakeup-pin defined\n");
}
#endif
sport->device_ctrl_rts = of_property_read_bool(np, "device-control-rts");
@@ -2239,7 +2239,7 @@ static int serial_pxa_probe(struct platform_device *dev)
serial_pxa_ports[sport->port.line] = sport;
uart_add_one_port(&serial_pxa_reg, &sport->port);
- dev_info(&dev->dev, "uart clk_rate: %lu\n", clk_get_rate(sport->fclk));
+ dev_dbg(&dev->dev, "uart clk_rate: %lu\n", clk_get_rate(sport->fclk));
platform_set_drvdata(dev, sport);
#ifdef CONFIG_PM
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 111111111111..222222222222 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -249,6 +249,7 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
int ret;
init_completion(&cmd->write_complete);
+ cmd->write_aborted = false;
cmd->fu = fu;
if (!cmd->data_len) {
@@ -264,11 +265,15 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
if (ret)
goto cleanup;
ret = usb_ep_queue(fu->ep_out, fu->bot_req_out, GFP_KERNEL);
- if (ret)
- pr_err("%s(%d)\n", __func__, __LINE__);
+ if (ret) {
+ pr_err("%s(%d): %d\n", __func__, __LINE__, ret);
+ goto cleanup;
+ }
wait_for_completion(&cmd->write_complete);
- target_execute_cmd(se_cmd);
+ if (!cmd->write_aborted)
+ target_execute_cmd(se_cmd);
+
cleanup:
return ret;
}
@@ -833,6 +838,7 @@ static int uasp_send_write_request(struct usbg_cmd *cmd)
int ret;
init_completion(&cmd->write_complete);
+ cmd->write_aborted = false;
cmd->fu = fu;
iu->tag = cpu_to_be16(cmd->tag);
@@ -864,9 +870,13 @@ static int uasp_send_write_request(struct usbg_cmd *cmd)
pr_err("%s(%d)\n", __func__, __LINE__);
}
+ if (ret)
+ goto cleanup;
+
wait_for_completion(&cmd->write_complete);
- target_execute_cmd(se_cmd);
+ if (!cmd->write_aborted)
+ target_execute_cmd(se_cmd);
cleanup:
return ret;
}
@@ -1105,7 +1115,7 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
stream->cmd = NULL;
target_put_sess_cmd(se_cmd);
transport_generic_free_cmd(&cmd->se_cmd, 0);
- return;
+ goto abort_completion;
}
if (req->status) {
@@ -1129,10 +1139,14 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
if (cmd->state == UASP_QUEUE_COMMAND &&
cmd->tmr_rsp == RC_OVERLAPPED_TAG) {
uasp_send_tm_response(cmd);
- return;
+ goto abort_completion;
}
transport_send_check_condition_and_sense(se_cmd,
TCM_CHECK_CONDITION_ABORT_CMD, 0);
+abort_completion:
+ cmd->write_aborted = true;
+ complete(&cmd->write_complete);
+ return;
}
static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
diff --git a/drivers/usb/gadget/function/tcm.h b/drivers/usb/gadget/function/tcm.h
index 111111111111..222222222222 100644
--- a/drivers/usb/gadget/function/tcm.h
+++ b/drivers/usb/gadget/function/tcm.h
@@ -75,6 +75,7 @@ struct usbg_cmd {
struct se_cmd se_cmd;
void *data_buf; /* used if no sg support available */
struct f_uas *fu;
+ bool write_aborted;
struct completion write_complete;
struct kref ref;
diff --git a/include/linux/mfd/spacemit/spacemit_pmic.h b/include/linux/mfd/spacemit/spacemit_pmic.h
index 111111111111..222222222222 100644
--- a/include/linux/mfd/spacemit/spacemit_pmic.h
+++ b/include/linux/mfd/spacemit/spacemit_pmic.h
@@ -197,6 +197,7 @@ struct mfd_match_data {
/* regulator: match data */
struct regulator_match_data {
int nr_desc;
+ int sleep_reg_offset;
const struct regulator_desc *desc;
const char *name;
};
diff --git a/include/linux/mfd/spacemit/spm8821.h b/include/linux/mfd/spacemit/spm8821.h
index 111111111111..222222222222 100644
--- a/include/linux/mfd/spacemit/spm8821.h
+++ b/include/linux/mfd/spacemit/spm8821.h
@@ -83,6 +83,8 @@ enum SPM8821_reg {
#define SPM8821_NON_RESET_REG 0xAB
#define SPM8821_RESTART_CFG_BIT_MSK 0x3
+#define SPM8821_SLEEP_REG_OFFSET 0x1
+
#define SPM8821_REGMAP_CONFIG \
static const struct regmap_config spm8821_regmap_config = { \
.reg_bits = 8, \
@@ -104,7 +106,7 @@ enum SPM8821_reg {
#define SPM8821_BUCK_LINER_RANGE \
static const struct linear_range spm8821_buck_ranges[] = { \
REGULATOR_LINEAR_RANGE(500000, 0x0, 0xaa, 5000), \
- REGULATOR_LINEAR_RANGE(1375000, 0xab, 0xfe, 25000), \
+ REGULATOR_LINEAR_RANGE(1375000, 0xab, 0xff, 25000), \
};
@@ -790,6 +792,7 @@ static struct regulator_match_data spm8821_regulator_match_data = { \
.nr_desc = ARRAY_SIZE(spm8821_reg), \
.desc = spm8821_reg, \
.name = "spm8821", \
+ .sleep_reg_offset = SPM8821_SLEEP_REG_OFFSET, \
};
#endif /* __SPM8821_H__ */
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index 111111111111..222222222222 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -342,4 +342,14 @@ enum scsi_version_descriptor {
SCSI_VERSION_DESCRIPTOR_SRP = 0x0940
};
+enum scsi_support_opcode {
+ SCSI_SUPPORT_NO_INFO = 0,
+ SCSI_SUPPORT_NOT_SUPPORTED = 1,
+ SCSI_SUPPORT_FULL = 3,
+ SCSI_SUPPORT_VENDOR = 5,
+};
+
+#define SCSI_CONTROL_MASK 0
+#define SCSI_GROUP_NUMBER_MASK 0
+
#endif /* _SCSI_PROTO_H_ */
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 111111111111..222222222222 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -91,6 +91,8 @@
#define DA_EMULATE_ALUA 0
/* Emulate SCSI2 RESERVE/RELEASE and Persistent Reservations by default */
#define DA_EMULATE_PR 1
+/* Emulation for REPORT SUPPORTED OPERATION CODES */
+#define DA_EMULATE_RSOC 1
/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
#define DA_ENFORCE_PR_ISIDS 1
/* Force SPC-3 PR Activate Persistence across Target Power Loss */
@@ -700,6 +702,7 @@ struct se_dev_attrib {
bool emulate_caw;
bool emulate_3pc;
bool emulate_pr;
+ bool emulate_rsoc;
enum target_prot_type pi_prot_type;
enum target_prot_type hw_pi_prot_type;
bool pi_prot_verify;
@@ -878,6 +881,21 @@ struct se_device {
struct mutex lun_reset_mutex;
};
+struct target_opcode_descriptor {
+ u8 support:3;
+ u8 serv_action_valid:1;
+ u8 opcode;
+ u16 service_action;
+ u32 cdb_size;
+ u8 specific_timeout;
+ u16 nominal_timeout;
+ u16 recommended_timeout;
+ bool (*enabled)(struct se_cmd *cmd);
+ void (*update_usage_bits)(u8 *usage_bits,
+ struct se_device *dev);
+ u8 usage_bits[];
+};
+
struct se_hba {
u16 hba_tpgt;
u32 hba_id;
diff --git a/init/version-timestamp.c b/init/version-timestamp.c
index 111111111111..222222222222 100644
--- a/init/version-timestamp.c
+++ b/init/version-timestamp.c
@@ -27,5 +27,5 @@ struct uts_namespace init_uts_ns = {
/* FIXED STRINGS! Don't touch! */
const char linux_banner[] =
- "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+ "Linux version " UTS_RELEASE " (" LINUX_VERSION_COMMITID ") (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 111111111111..222222222222 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -23,6 +23,13 @@
#include <sound/jack.h>
#include "es8316.h"
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+/* 12.288MHz MCLK, 48kHz LRCK */
+#define NR_SUPPORTED_MCLK_LRCK_RATIOS 4
+static const unsigned int supported_mclk_lrck_ratios[] = {
+ 256, 384, 512, 768
+};
+#else
/* In slave mode at single speed, the codec is documented as accepting 5
* MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
* Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
@@ -31,6 +38,7 @@
static const unsigned int supported_mclk_lrck_ratios[] = {
256, 384, 400, 512, 768, 1024
};
+#endif
struct es8316_priv {
struct mutex lock;
@@ -375,6 +383,7 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
if (freq == 0)
return 0;
+ dev_dbg(component->dev, "set sysclk freq: %d\n", freq);
ret = clk_set_rate(es8316->mclk, freq);
if (ret)
return ret;
@@ -471,9 +480,12 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
u16 lrck_divider;
int i;
+ dev_dbg(component->dev, "set rate: %d\n", params_rate(params));
+
/* Validate supported sample rates that are autodetected from MCLK */
for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
const unsigned int ratio = supported_mclk_lrck_ratios[i];
+ dev_dbg(component->dev, "ratio %d, es8316->sysclk: %d\n", ratio, es8316->sysclk);
if (es8316->sysclk % ratio != 0)
continue;
@@ -505,6 +517,8 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ dev_dbg(component->dev, "wordlen: %d, bclk_divider: %d\n", wordlen, bclk_divider);
+
snd_soc_component_update_bits(component, ES8316_SERDATA_DAC,
ES8316_SERDATA2_LEN_MASK, wordlen);
snd_soc_component_update_bits(component, ES8316_SERDATA_ADC,
@@ -762,6 +776,20 @@ static int es8316_probe(struct snd_soc_component *component)
*/
snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32);
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ /*DAC*/
+ snd_soc_component_write(component, ES8316_CPHP_ICAL_VOL, 0x00);
+ snd_soc_component_write(component, ES8316_HPMIX_VOL, 0xBB);
+ snd_soc_component_write(component, ES8316_DAC_VOLL, 0x11);
+ snd_soc_component_write(component, ES8316_DAC_VOLR, 0x01);
+ snd_soc_component_write(component, ES8316_HPMIX_SWITCH, 0x88);
+
+ /*ADC*/
+ snd_soc_component_write(component, ES8316_ADC_PGAGAIN, 0x70);
+ snd_soc_component_write(component, ES8316_ADC_VOLUME, 0x2A);
+ snd_soc_component_write(component, ES8316_ADC_PDN_LINSEL, 0x10);
+#endif
+
return 0;
}
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index 111111111111..222222222222 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -47,6 +47,11 @@ struct es8326_priv {
int jack_remove_retry;
#ifdef SPACEMIT_CONFIG_CODEC_ES8326
int spk_ctl_gpio;
+ int hp_gpio;
+ int hp_irq;
+ int mic_gpio;
+ int mic_irq;
+ struct delayed_work hpmic_detect_work;
#endif
};
@@ -465,9 +470,7 @@ static int es8326_pcm_hw_params(struct snd_pcm_substream *substream,
coeff_div = coeff_div_v3;
array = ARRAY_SIZE(coeff_div_v3);
}
-#ifdef SPACEMIT_CONFIG_CODEC_ES8326
- es8326->sysclk = params_rate(params) * 64;
-#endif
+
coeff = get_coeff(es8326->sysclk, params_rate(params), array, coeff_div);
/* bit size */
switch (params_format(params)) {
@@ -878,6 +881,72 @@ static irqreturn_t es8326_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#ifdef SPACEMIT_CONFIG_CODEC_ES8326
+static void es8326_hpmic_detect_handler(struct work_struct *work)
+{
+ struct es8326_priv *es8326 =
+ container_of(work, struct es8326_priv, hpmic_detect_work.work);
+ struct snd_soc_component *comp = es8326->component;
+ bool hp_status = 0, mic_status = 0;
+ u8 jack_status;
+
+ if (es8326->hp_gpio >= 0) {
+ hp_status = !gpio_get_value(es8326->hp_gpio);
+ }
+ if (es8326->mic_gpio >= 0) {
+ mic_status = !gpio_get_value(es8326->mic_gpio);
+ }
+ jack_status = hp_status | (mic_status << 1);
+ dev_dbg(comp->dev, "jack_status:%d\n", jack_status);
+ if ((jack_status & SND_JACK_HEADSET) == 0) {
+ /* Jack unplugged or spurious IRQ */
+ es8326_disable_micbias(es8326->component);
+ es8326->hp = 0;
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
+ regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a);
+ regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03);
+
+ } else {
+ if (es8326->hp == 0) {
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
+ es8326_enable_micbias(es8326->component);
+ usleep_range(50000, 70000);
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
+ regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f);
+ regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08);
+ usleep_range(10000, 15000);
+ es8326->hp = 1;
+ regmap_write(es8326->regmap, ES8326_ADC_SCALE, 0x33);
+ regmap_update_bits(es8326->regmap, ES8326_PGA_PDN,
+ 0x08, 0x08);
+ regmap_update_bits(es8326->regmap, ES8326_PGAGAIN,
+ 0x80, 0x80);
+ regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x00);
+ regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x00);
+ regmap_update_bits(es8326->regmap, ES8326_PGA_PDN,
+ 0x08, 0x00);
+ usleep_range(10000, 15000);
+ }
+ }
+ snd_soc_jack_report(es8326->jack,
+ jack_status,
+ SND_JACK_HEADSET);
+ return;
+}
+
+static irqreturn_t es8326_irq_hpmic(int irq, void *dev_id)
+{
+ struct es8326_priv *es8326 = dev_id;
+
+ if (!es8326->jack)
+ goto out;
+ queue_delayed_work(system_wq, &es8326->hpmic_detect_work,
+ msecs_to_jiffies(100));
+out:
+ return IRQ_HANDLED;
+}
+#endif
+
static int es8326_calibrate(struct snd_soc_component *component)
{
struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
@@ -1209,7 +1278,14 @@ static void es8326_enable_jack_detect(struct snd_soc_component *component,
es8326->jack = jack;
mutex_unlock(&es8326->lock);
+#ifdef SPACEMIT_CONFIG_CODEC_ES8326
+ if (es8326->irq > 0)
+ es8326_irq(es8326->irq, es8326);
+ else
+ es8326_irq_hpmic(es8326->irq, es8326);
+#else
es8326_irq(es8326->irq, es8326);
+#endif
}
static void es8326_disable_jack_detect(struct snd_soc_component *component)
@@ -1292,6 +1368,10 @@ static int es8326_i2c_probe(struct i2c_client *i2c,
es8326_jack_detect_handler);
INIT_DELAYED_WORK(&es8326->button_press_work,
es8326_jack_button_handler);
+#ifdef SPACEMIT_CONFIG_CODEC_ES8326
+ INIT_DELAYED_WORK(&es8326->hpmic_detect_work,
+ es8326_hpmic_detect_handler);
+#endif
/* ES8316 is level-based while ES8326 is edge-based */
ret = devm_request_threaded_irq(&i2c->dev, es8326->irq, NULL, es8326_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -1319,6 +1399,36 @@ static int es8326_i2c_probe(struct i2c_client *i2c,
}
es8326_enable_spk(es8326, false);
}
+ es8326->hp_gpio = of_get_named_gpio_flags(i2c->dev.of_node,
+ "hp-detect-gpio", 0, &flags);
+ if (es8326->hp_gpio < 0) {
+ dev_info(&i2c->dev, "Can not read property hp-detect-gpio\n");
+ es8326->hp_gpio = -1;
+ } else {
+ es8326->hp_irq = gpio_to_irq(es8326->hp_gpio);
+ ret = request_irq(es8326->hp_irq, es8326_irq_hpmic,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "es8326-hp-irq", es8326);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to request hp-irq\n");
+ return ret;
+ }
+ }
+ es8326->mic_gpio = of_get_named_gpio_flags(i2c->dev.of_node,
+ "mic-detect-gpio", 0, &flags);
+ if (es8326->mic_gpio < 0) {
+ dev_info(&i2c->dev, "Can not read property mic-detect-gpio\n");
+ es8326->mic_gpio = -1;
+ } else {
+ es8326->mic_irq = gpio_to_irq(es8326->mic_gpio);
+ ret = request_irq(es8326->mic_irq, es8326_irq_hpmic,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "es8326-mic-irq", es8326);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to request mic-irq\n");
+ return ret;
+ }
+ }
#endif
es8326->mclk = devm_clk_get_optional(&i2c->dev, "mclk");
if (IS_ERR(es8326->mclk)) {
diff --git a/sound/soc/spacemit/spacemit-snd-card.c b/sound/soc/spacemit/spacemit-snd-card.c
index 111111111111..222222222222 100644
--- a/sound/soc/spacemit/spacemit-snd-card.c
+++ b/sound/soc/spacemit/spacemit-snd-card.c
@@ -21,6 +21,54 @@
#define CELL "#sound-dai-cells"
#define PREFIX "simple-audio-card,"
+
+int spacemit_simple_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai *sdai;
+ struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num);
+ unsigned int mclk, mclk_fs = 0;
+ int i, ret;
+
+ if (props->mclk_fs)
+ mclk_fs = props->mclk_fs;
+
+ if (mclk_fs) {
+ struct snd_soc_component *component;
+ mclk = params_rate(params) * mclk_fs;
+
+ /* Ensure sysclk is set on all components in case any
+ * (such as platform components) are missed by calls to
+ * snd_soc_dai_set_sysclk.
+ */
+ for_each_rtd_components(rtd, i, component) {
+ ret = snd_soc_component_set_sysclk(component, 0, 0,
+ mclk, SND_SOC_CLOCK_IN);
+ if (ret && ret != -ENOTSUPP)
+ return ret;
+ }
+
+ for_each_rtd_codec_dais(rtd, i, sdai) {
+ ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_IN);
+ if (ret && ret != -ENOTSUPP)
+ return ret;
+ }
+
+ for_each_rtd_cpu_dais(rtd, i, sdai) {
+ ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_OUT);
+ if (ret && ret != -ENOTSUPP)
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static const struct snd_soc_ops simple_ops = {
+ .hw_params = spacemit_simple_hw_params,
+};
+
static int asoc_simple_parse_dai(struct device_node *node,
struct snd_soc_dai_link_component *dlc,
int *is_single_link)
@@ -161,6 +209,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
char prop[128];
char *prefix = "";
int ret, single_cpu;
+ unsigned int val = 0;
if (is_top_level_node)
prefix = PREFIX;
@@ -220,6 +269,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
dai_link->init = asoc_simple_card_jack_init;
}
+ dai_link->ops = &simple_ops;
+ if (!of_property_read_u32(node, "spacemit,mclk-fs", &val)) {
+ priv->dai_props->mclk_fs = val;
+ } else {
+ priv->dai_props->mclk_fs = 256;
+ }
asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu);
asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus);
diff --git a/sound/soc/spacemit/spacemit-snd-i2s.c b/sound/soc/spacemit/spacemit-snd-i2s.c
index 111111111111..222222222222 100644
--- a/sound/soc/spacemit/spacemit-snd-i2s.c
+++ b/sound/soc/spacemit/spacemit-snd-i2s.c
@@ -85,6 +85,7 @@ struct sspa_priv {
int dai_id_pre;
int running_cnt;
struct platform_device *i2splatdev;
+ unsigned int sysclk;
};
static void i2s_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val)
@@ -117,6 +118,15 @@ static void i2s_sspa_shutdown(struct snd_pcm_substream *substream,
static int i2s_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
+ struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
+
+ if (sspa_priv->running_cnt)
+ return 0;
+
+ if (sspa_priv->sysclk == freq)
+ return 0;
+
+ sspa_priv->sysclk = freq;
return 0;
}
@@ -207,13 +217,35 @@ static int i2s_sspa_hw_params(struct snd_pcm_substream *substream,
struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
struct ssp_device *sspa = sspa_priv->sspa;
struct snd_dmaengine_dai_dma_data *dma_params;
+ unsigned int mclk_fs, val, target;
- pr_debug("%s, format=0x%x\n", __FUNCTION__, params_format(params));
dma_params = &sspa_priv->dma_params[substream->stream];
dma_params->addr = (sspa->phys_base + DATAR);
dma_params->maxburst = 32;
dma_params->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params);
+
+ if (sspa_priv->running_cnt)
+ return 0;
+
+ mclk_fs = sspa_priv->sysclk / (params_rate(params));
+ switch (mclk_fs) {
+ case 64:
+ target = SYSCLK_BASE_156M | 0 << 27| 4 << 15 | 200; //64fs
+ break;
+ case 128:
+ target = SYSCLK_BASE_156M | 1 << 27| 8 << 15 | 200; //128fs
+ break;
+ case 256:
+ target = SYSCLK_BASE_156M | 3 << 27| 16 << 15 | 200; //256fs
+ break;
+ default:
+ target = SYSCLK_BASE_156M | 3 << 27| 16 << 15 | 200; //256fs
+ break;
+ }
+ val = __raw_readl(sspa->pmumain + ISCCR1);
+ val = val & ~0x5FFFFFFF;
+ __raw_writel(val | target, sspa->pmumain + ISCCR1);
return 0;
}
@@ -274,9 +306,6 @@ static int i2s_sspa_probe(struct snd_soc_dai *dai)
struct sspa_priv *priv = dev_get_drvdata(dai->dev);
struct ssp_device *sspa = priv->sspa;
unsigned int sspa_clk = 0;
- pr_debug("%s\n", __FUNCTION__);
- //init clock
- __raw_writel((SYSCLK_BASE_156M | BITCLK_DIV_468| FRAME_48K_I2S | 200), sspa->pmumain + ISCCR1);
if (dai->id == 0)
{
@@ -372,7 +401,7 @@ static int asoc_i2s_sspa_probe(struct platform_device *pdev)
struct resource *res;
u8 dai_id = 0;
- printk("enter %s\n", __FUNCTION__);
+ pr_debug("enter %s\n", __FUNCTION__);
priv = devm_kzalloc(&pdev->dev,
sizeof(struct sspa_priv), GFP_KERNEL);
if (!priv) {
@@ -456,7 +485,7 @@ static struct platform_driver asoc_i2s_sspa_driver = {
#if IS_MODULE(CONFIG_SND_SOC_SPACEMIT)
int spacemit_snd_register_i2s_pdrv(void)
{
- printk("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __FUNCTION__);
return platform_driver_register(&asoc_i2s_sspa_driver);
}
diff --git a/sound/soc/spacemit/spacemit-snd-pcm-dma.c b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
index 111111111111..222222222222 100644
--- a/sound/soc/spacemit/spacemit-snd-pcm-dma.c
+++ b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
@@ -731,7 +731,7 @@ static int spacemit_snd_pcm_new(struct snd_soc_component *component, struct snd_
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
- printk("%s enter, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
+ pr_debug("%s enter, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
if (!component) {
pr_err("%s: coundn't find component %s\n", __FUNCTION__, DRV_NAME);
@@ -745,7 +745,7 @@ static int spacemit_snd_pcm_new(struct snd_soc_component *component, struct snd_
}
if (dev->dmadata->dma_id == DMA_HDMI) {
chan_num = 1;
- printk("%s playback_only, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
+ pr_debug("%s playback_only, dev=%s\n", __FUNCTION__, dev_name(rtd->dev));
}else{
chan_num = 2;
}
@@ -810,7 +810,7 @@ static void spacemit_snd_pcm_remove(struct snd_soc_component *component)
int chan_num;
struct spacemit_snd_soc_device *dev = snd_soc_component_get_drvdata(component);
- pr_info("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __FUNCTION__);
if (dev->dmadata->dma_id == DMA_HDMI) {
chan_num = 1;
@@ -969,12 +969,12 @@ static int spacemit_snd_dma_pdev_probe(struct platform_device *pdev)
return -ENOMEM;
}
- printk("%s enter: dev name %s\n", __func__, dev_name(&pdev->dev));
+ pr_debug("%s enter: dev name %s\n", __func__, dev_name(&pdev->dev));
if (of_device_is_compatible(np, "spacemit,spacemit-snd-dma-hdmi")){
device->dmadata->dma_id = DMA_HDMI;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- printk("%s, start=0x%lx, end=0x%lx\n", __FUNCTION__, (unsigned long)res->start, (unsigned long)res->end);
+ pr_debug("%s, start=0x%lx, end=0x%lx\n", __FUNCTION__, (unsigned long)res->start, (unsigned long)res->end);
priv.phy_addr = res->start;
priv.buf_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv.buf_base)) {
@@ -1026,7 +1026,7 @@ static struct platform_driver spacemit_snd_dma_pdrv = {
#if IS_MODULE(CONFIG_SND_SOC_SPACEMIT)
int spacemit_snd_register_dmaclient_pdrv(void)
{
- printk("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __FUNCTION__);
return platform_driver_register(&spacemit_snd_dma_pdrv);
}
EXPORT_SYMBOL(spacemit_snd_register_dmaclient_pdrv);
diff --git a/sound/soc/spacemit/spacemit-snd-sspa.c b/sound/soc/spacemit/spacemit-snd-sspa.c
index 111111111111..222222222222 100644
--- a/sound/soc/spacemit/spacemit-snd-sspa.c
+++ b/sound/soc/spacemit/spacemit-snd-sspa.c
@@ -100,7 +100,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
struct snd_dmaengine_dai_dma_data *dma_params;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- printk("%s, format=0x%x\n", __FUNCTION__, params_format(params));
+ pr_debug("%s, format=0x%x\n", __FUNCTION__, params_format(params));
dma_params = sspa_priv->dma_params;
dma_params->maxburst = 32;
dma_params->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
--
Armbian