
On Thu, Jun 18, 2020 at 01:54:37AM +0530, Jagan Teki wrote:
DM_VIDEO migration deadline is already expired, but around 80 Allwinner boards are still using video in a legacy way.
===================== WARNING ====================== This board does not use CONFIG_DM_VIDEO Please update the board to use CONFIG_DM_VIDEO before the v2019.07 release. Failure to update by the deadline may result in board removal. See doc/driver-model/migration.rst for more info. ====================================================
So let's live these boards on the tree before the video maintainer removes it by converting in to DM_VIDEO.
Tested in Bananapi M1+ Plus 1920x1200 HDMI out.
Signed-off-by: Jagan Teki jagan@amarulasolutions.com
Changes for v2:
- add BMP support
arch/arm/mach-sunxi/Kconfig | 4 +- drivers/video/sunxi/sunxi_display.c | 264 ++++++++++++++++------------ include/configs/sunxi-common.h | 17 -- scripts/config_whitelist.txt | 1 - 4 files changed, 157 insertions(+), 129 deletions(-)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index be0822bfb7..7d2fb55ff0 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -758,8 +758,10 @@ config VIDEO_SUNXI depends on !MACH_SUN9I depends on !MACH_SUN50I depends on !MACH_SUN50I_H6
- select VIDEO
- select DM_VIDEO
- select DISPLAY imply VIDEO_DT_SIMPLEFB
- imply CMD_BMP default y ---help--- Say Y here to add support for using a cfb console on the HDMI, LCD
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index f52aba4d21..fb51b0c5ba 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -7,6 +7,8 @@ */
#include <common.h> +#include <display.h> +#include <dm.h> #include <cpu_func.h> #include <efi_loader.h> #include <init.h> @@ -28,7 +30,9 @@ #include <fdt_support.h> #include <i2c.h> #include <malloc.h> +#include <video.h> #include <video_fb.h> +#include <dm/uclass-internal.h> #include "../videomodes.h" #include "../anx9804.h" #include "../hitachi_tx18d42vm_lcd.h" @@ -45,6 +49,13 @@
DECLARE_GLOBAL_DATA_PTR;
+enum {
- /* Maximum LCD size we support */
- LCD_MAX_WIDTH = 3840,
- LCD_MAX_HEIGHT = 2160,
- LCD_MAX_LOG2_BPP = VIDEO_BPP32,
+};
Why is that an enum? Those three values don't have any relationship with each other.
enum sunxi_monitor { sunxi_monitor_none, sunxi_monitor_dvi, @@ -59,12 +70,11 @@ enum sunxi_monitor { #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
struct sunxi_display {
- GraphicDevice graphic_device; enum sunxi_monitor monitor; unsigned int depth; unsigned int fb_addr; unsigned int fb_size;
-} sunxi_display; +};
This looks unrelated?
const struct ctfb_res_modes composite_video_modes[2] = { /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */ @@ -214,7 +224,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf) return r; }
-static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode, +static int sunxi_hdmi_edid_get_mode(struct sunxi_display *sunxi_display,
struct ctfb_res_modes *mode, bool verbose_mode)
{ struct edid1_info edid1; @@ -291,14 +302,14 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode, }
/* Check for basic audio support, if found enable hdmi output */
- sunxi_display.monitor = sunxi_monitor_dvi;
sunxi_display->monitor = sunxi_monitor_dvi; for (i = 0; i < ext_blocks; i++) { if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG || cea681[i].revision < 2) continue;
if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
sunxi_display.monitor = sunxi_monitor_hdmi;
sunxi_display->monitor = sunxi_monitor_hdmi;
}
return 0;
@@ -414,9 +425,9 @@ static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode, static void sunxi_frontend_enable(void) {} #endif
-static bool sunxi_is_composite(void) +static bool sunxi_is_composite(enum sunxi_monitor monitor) {
- switch (sunxi_display.monitor) {
- switch (monitor) { case sunxi_monitor_none: case sunxi_monitor_dvi: case sunxi_monitor_hdmi:
@@ -473,7 +484,8 @@ static const u32 sunxi_rgb2yuv_coef[12] = { };
static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
unsigned int address)
unsigned int address,
enum sunxi_monitor monitor)
{ struct sunxi_de_be_reg * const de_be = (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; @@ -502,7 +514,7 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode, #endif SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
- if (sunxi_is_composite()) {
- if (sunxi_is_composite(monitor)) { writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE, &de_be->output_color_ctrl); for (i = 0; i < 12; i++)
@@ -616,7 +628,8 @@ static void sunxi_lcdc_backlight_enable(void) gpio_direction_output(pin, PWM_ON); }
-static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, +static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display *sunxi_display,
const struct ctfb_res_modes *mode, bool for_ext_vga_dac)
{ struct sunxi_lcdc_reg * const lcdc = @@ -643,17 +656,18 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, }
lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
sunxi_is_composite());
sunxi_is_composite(sunxi_display->monitor));
video_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
}
#if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, int *clk_div, int *clk_double,
bool use_portd_hvsync)
bool use_portd_hvsync,
enum sunxi_monitor monitor)
{ struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; @@ -663,7 +677,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
video_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
sunxi_is_composite());
sunxi_is_composite(monitor));
if (use_portd_hvsync) { sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
@@ -671,7 +685,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, }
lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
sunxi_is_composite());
sunxi_is_composite(monitor));
} #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
@@ -725,7 +739,8 @@ static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode) }
static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
int clk_div, int clk_double)
int clk_div, int clk_double,
enum sunxi_monitor monitor)
{ struct sunxi_hdmi_reg * const hdmi = (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; @@ -734,7 +749,7 @@ static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode, /* Write clear interrupt status bits */ writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
- if (sunxi_display.monitor == sunxi_monitor_hdmi)
if (monitor == sunxi_monitor_hdmi) sunxi_hdmi_setup_info_frames(mode);
/* Set input sync enable */
@@ -789,7 +804,7 @@ static void sunxi_hdmi_enable(void)
#if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
-static void sunxi_tvencoder_mode_set(void) +static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor) { struct sunxi_ccm_reg * const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; @@ -801,7 +816,7 @@ static void sunxi_tvencoder_mode_set(void) /* Clock on */ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
- switch (sunxi_display.monitor) {
- switch (monitor) { case sunxi_monitor_vga: tvencoder_mode_set(tve, tve_mode_vga); break;
@@ -896,26 +911,28 @@ static void sunxi_engines_init(void) sunxi_drc_init(); }
-static void sunxi_mode_set(const struct ctfb_res_modes *mode, +static void sunxi_mode_set(struct sunxi_display *sunxi_display,
const struct ctfb_res_modes *mode, unsigned int address)
{
- enum sunxi_monitor monitor = sunxi_display->monitor; int __maybe_unused clk_div, clk_double; struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; struct sunxi_tve_reg * __maybe_unused const tve = (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
- switch (sunxi_display.monitor) {
- switch (sunxi_display->monitor) { case sunxi_monitor_none: break; case sunxi_monitor_dvi: case sunxi_monitor_hdmi:
#ifdef CONFIG_VIDEO_HDMI
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
sunxi_hdmi_mode_set(mode, clk_div, clk_double);
sunxi_composer_mode_set(mode, address, monitor);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
sunxi_composer_enable();sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor);
lcdc_enable(lcdc, sunxi_display.depth);
sunxi_hdmi_enable();lcdc_enable(lcdc, sunxi_display->depth);
#endif break; @@ -930,7 +947,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, axp_set_eldo(3, 1800); anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4, ANX9804_DATA_RATE_1620M,
sunxi_display.depth);
} if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) { mdelay(50); /* Wait for lcd controller power on */sunxi_display->depth);
@@ -942,10 +959,10 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */ i2c_set_bus_num(orig_i2c_bus); }
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon0_mode_set(mode, false);
sunxi_composer_mode_set(mode, address, monitor);
sunxi_composer_enable();sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false);
lcdc_enable(lcdc, sunxi_display.depth);
lcdc_enable(lcdc, sunxi_display->depth);
#ifdef CONFIG_VIDEO_LCD_SSD2828 sunxi_ssd2828_init(mode); #endif @@ -953,17 +970,17 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, break; case sunxi_monitor_vga: #ifdef CONFIG_VIDEO_VGA
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
sunxi_tvencoder_mode_set();
sunxi_composer_mode_set(mode, address, monitor);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor);
sunxi_composer_enable();sunxi_tvencoder_mode_set(monitor);
lcdc_enable(lcdc, sunxi_display.depth);
tvencoder_enable(tve);lcdc_enable(lcdc, sunxi_display->depth);
#elif defined CONFIG_VIDEO_VGA_VIA_LCD
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon0_mode_set(mode, true);
sunxi_composer_mode_set(mode, address, monitor);
sunxi_composer_enable();sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true);
lcdc_enable(lcdc, sunxi_display.depth);
sunxi_vga_external_dac_enable();lcdc_enable(lcdc, sunxi_display->depth);
#endif break; @@ -972,11 +989,11 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, case sunxi_monitor_composite_pal_m: case sunxi_monitor_composite_pal_nc: #ifdef CONFIG_VIDEO_COMPOSITE
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
sunxi_tvencoder_mode_set();
sunxi_composer_mode_set(mode, address, monitor);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
sunxi_composer_enable();sunxi_tvencoder_mode_set(monitor);
lcdc_enable(lcdc, sunxi_display.depth);
tvencoder_enable(tve);lcdc_enable(lcdc, sunxi_display->depth);
#endif break; @@ -999,11 +1016,6 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor) } }
-ulong board_get_usable_ram_top(ulong total_size) -{
- return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
-}
I couldn't find how you're allocating and reserving the video buffer now for simplefb to use later on.
static bool sunxi_has_hdmi(void) { #ifdef CONFIG_VIDEO_HDMI @@ -1052,9 +1064,11 @@ static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi) return sunxi_monitor_none; }
-void *video_hw_init(void) +static int sunxi_de_probe(struct udevice *dev) {
- static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
- struct video_priv *uc_priv = dev_get_uclass_priv(dev);
- struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
- struct sunxi_display *sunxi_display = dev_get_priv(dev); const struct ctfb_res_modes *mode; struct ctfb_res_modes custom; const char *options;
@@ -1067,10 +1081,8 @@ void *video_hw_init(void) char mon[16]; char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
- memset(&sunxi_display, 0, sizeof(struct sunxi_display));
- video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
&sunxi_display.depth, &options);
&sunxi_display->depth, &options);
#ifdef CONFIG_VIDEO_HDMI hpd = video_get_option_int(options, "hpd", 1); hpd_delay = video_get_option_int(options, "hpd_delay", 500); @@ -1078,35 +1090,35 @@ void *video_hw_init(void) #endif overscan_x = video_get_option_int(options, "overscan_x", -1); overscan_y = video_get_option_int(options, "overscan_y", -1);
- sunxi_display.monitor = sunxi_get_default_mon(true);
- sunxi_display->monitor = sunxi_get_default_mon(true); video_get_option_string(options, "monitor", mon, sizeof(mon),
sunxi_get_mon_desc(sunxi_display.monitor));
for (i = 0; i <= SUNXI_MONITOR_LAST; i++) { if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {sunxi_get_mon_desc(sunxi_display->monitor));
sunxi_display.monitor = i;
} } if (i > SUNXI_MONITOR_LAST) printf("Unknown monitor: '%s', falling back to '%s'\n",sunxi_display->monitor = i; break;
mon, sunxi_get_mon_desc(sunxi_display.monitor));
mon, sunxi_get_mon_desc(sunxi_display->monitor));
#ifdef CONFIG_VIDEO_HDMI /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
- if (sunxi_display.monitor == sunxi_monitor_dvi ||
sunxi_display.monitor == sunxi_monitor_hdmi) {
- if (sunxi_display->monitor == sunxi_monitor_dvi ||
/* Always call hdp_detect, as it also enables clocks, etc. */ hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1); if (hdmi_present && edid) { printf("HDMI connected: ");sunxi_display->monitor == sunxi_monitor_hdmi) {
if (sunxi_hdmi_edid_get_mode(&custom, true) == 0)
} /* Fall back to EDID in case HPD failed */ if (edid && !hdmi_present) {if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0) mode = &custom; else hdmi_present = false;
if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) {
if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) { mode = &custom; hdmi_present = true; }
@@ -1114,38 +1126,39 @@ void *video_hw_init(void) /* Shut down when display was not found */ if ((hpd || edid) && !hdmi_present) { sunxi_hdmi_shutdown();
sunxi_display.monitor = sunxi_get_default_mon(false);
} /* else continue with hdmi/dvi without a cable connected */ }sunxi_display->monitor = sunxi_get_default_mon(false);
#endif
- switch (sunxi_display.monitor) {
- switch (sunxi_display->monitor) { case sunxi_monitor_none:
return NULL;
printf("Unknown monitor\n");
case sunxi_monitor_dvi: case sunxi_monitor_hdmi: if (!sunxi_has_hdmi()) { printf("HDMI/DVI not supported on this board\n");return -EINVAL;
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
sunxi_display->monitor = sunxi_monitor_none;
} break; case sunxi_monitor_lcd: if (!sunxi_has_lcd()) { printf("LCD not supported on this board\n");return -EINVAL;
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
sunxi_display->monitor = sunxi_monitor_none;
}return -EINVAL;
sunxi_display.depth = video_get_params(&custom, lcd_mode);
mode = &custom; break; case sunxi_monitor_vga: if (!sunxi_has_vga()) { printf("VGA not supported on this board\n");sunxi_display->depth = video_get_params(&custom, lcd_mode);
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
sunxi_display->monitor = sunxi_monitor_none;
}return -EINVAL;
sunxi_display.depth = 18;
break; case sunxi_monitor_composite_pal: case sunxi_monitor_composite_ntsc:sunxi_display->depth = 18;
@@ -1153,85 +1166,103 @@ void *video_hw_init(void) case sunxi_monitor_composite_pal_nc: if (!sunxi_has_composite()) { printf("Composite video not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
sunxi_display->monitor = sunxi_monitor_none;
}return -EINVAL;
if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
if (sunxi_display->monitor == sunxi_monitor_composite_pal ||
else mode = &composite_video_modes[1];sunxi_display->monitor == sunxi_monitor_composite_pal_nc) mode = &composite_video_modes[0];
sunxi_display.depth = 24;
sunxi_display->depth = 24;
break; }
/* Yes these defaults are quite high, overscan on composite sucks... */ if (overscan_x == -1)
overscan_x = sunxi_is_composite() ? 32 : 0;
if (overscan_y == -1)overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0;
overscan_y = sunxi_is_composite() ? 20 : 0;
overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0;
- sunxi_display.fb_size =
(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
- sunxi_display->fb_size = plat->size; overscan_offset = (overscan_y * mode->xres + overscan_x) * 4; /* We want to keep the fb_base for simplefb page aligned, where as
if (overscan_offset)
- the sunxi dma engines will happily accept an unaligned address. */
sunxi_display.fb_size += 0x1000;
- if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
printf("Error need %dkB for fb, but only %dkB is reserved\n",
sunxi_display.fb_size >> 10,
CONFIG_SUNXI_MAX_FB_SIZE >> 10);
return NULL;
- }
sunxi_display->fb_size += 0x1000;
printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n", mode->xres, mode->yres, (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
sunxi_get_mon_desc(sunxi_display.monitor),
sunxi_get_mon_desc(sunxi_display->monitor), overscan_x, overscan_y);
- gd->fb_base = gd->bd->bi_dram[0].start +
gd->bd->bi_dram[0].size - sunxi_display.fb_size;
- sunxi_display->fb_addr = plat->base; sunxi_engines_init();
#ifdef CONFIG_EFI_LOADER
- efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
- efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size, EFI_RESERVED_MEMORY_TYPE);
#endif
- fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
- sunxi_display.fb_addr = gd->fb_base;
- fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_BASE; if (overscan_offset) { fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
flush_cache(gd->fb_base, sunxi_display.fb_size);
sunxi_display->fb_addr += (overscan_offset + 0xfff) & ~0xfff;
memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size);
}flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size);
- sunxi_mode_set(mode, fb_dma_addr);
sunxi_mode_set(sunxi_display, mode, fb_dma_addr);
/*
- These are the only members of this structure that are used. All the
- others are driver specific. The pitch is stored in plnSizeX.
*/
- graphic_device->frameAdrs = sunxi_display.fb_addr;
- graphic_device->gdfIndex = GDF_32BIT_X888RGB;
- graphic_device->gdfBytesPP = 4;
- graphic_device->winSizeX = mode->xres - 2 * overscan_x;
- graphic_device->winSizeY = mode->yres - 2 * overscan_y;
- graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
- return graphic_device;
- uc_priv->bpix = VIDEO_BPP32;
- uc_priv->xsize = mode->xres;
- uc_priv->ysize = mode->yres;
- video_set_flush_dcache(dev, 1);
This is new. You should explain in a separate patch why the flush_cache above isn't enough.
Maxime