No more allocations everywhere
This commit is contained in:
parent
c0132fdba2
commit
656065160c
101
sharp.c
101
sharp.c
@ -49,6 +49,9 @@ struct sharp_memory_panel {
|
|||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
struct spi_transfer *spi_3_xfers;
|
||||||
|
unsigned char *cmd_buf;
|
||||||
|
unsigned char *trailer_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct sharp_memory_panel *drm_to_panel(struct drm_device *drm)
|
static inline struct sharp_memory_panel *drm_to_panel(struct drm_device *drm)
|
||||||
@ -73,18 +76,19 @@ static void vcom_timer_callback(struct timer_list *t)
|
|||||||
static int sharp_memory_spi_clear_screen(struct sharp_memory_panel *panel)
|
static int sharp_memory_spi_clear_screen(struct sharp_memory_panel *panel)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char tx_buf[2];
|
|
||||||
struct spi_transfer tr;
|
|
||||||
|
|
||||||
// Create screen clear command SPI transfer
|
// Create screen clear command SPI transfer
|
||||||
tx_buf[0] = CMD_CLEAR_SCREEN;
|
panel->cmd_buf[0] = CMD_CLEAR_SCREEN;
|
||||||
tx_buf[1] = 0;
|
panel->spi_3_xfers[0].tx_buf = panel->cmd_buf;
|
||||||
tr.tx_buf = &tx_buf;
|
panel->spi_3_xfers[0].len = 1;
|
||||||
tr.len = 2;
|
panel->trailer_buf[0] = 0;
|
||||||
|
panel->spi_3_xfers[1].tx_buf = panel->trailer_buf;
|
||||||
|
panel->spi_3_xfers[1].len = 1;
|
||||||
|
|
||||||
|
// Write clear screen command
|
||||||
ndelay(80);
|
ndelay(80);
|
||||||
gpio_set_value(GPIO_SCS, 1);
|
gpio_set_value(GPIO_SCS, 1);
|
||||||
rc = spi_sync_transfer(panel->spi, &tr, 1);
|
rc = spi_sync_transfer(panel->spi, panel->spi_3_xfers, 2);
|
||||||
gpio_set_value(GPIO_SCS, 0);
|
gpio_set_value(GPIO_SCS, 0);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -98,51 +102,31 @@ static inline u8 sharp_memory_reverse_byte(u8 b)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sharp_memory_spi_write_tagged_line(struct sharp_memory_panel *panel,
|
static int sharp_memory_spi_write_tagged_lines(struct sharp_memory_panel *panel,
|
||||||
const void *line_data, size_t len)
|
void *line_data, size_t len)
|
||||||
{
|
{
|
||||||
void *tx_buf = NULL;
|
int rc;
|
||||||
struct spi_transfer tr[3] = {};
|
|
||||||
u8 *command_buf, *trailer_buf;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
command_buf = kmalloc(2, GFP_KERNEL);
|
|
||||||
if (!command_buf) {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
trailer_buf = kzalloc(2, GFP_KERNEL);
|
|
||||||
if (!trailer_buf) {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write line command
|
// Write line command
|
||||||
command_buf[0] = 0b10000000;
|
panel->cmd_buf[0] = 0b10000000;
|
||||||
tr[0].tx_buf = command_buf;
|
panel->spi_3_xfers[0].tx_buf = panel->cmd_buf;
|
||||||
tr[0].len = 1;
|
panel->spi_3_xfers[0].len = 1;
|
||||||
|
|
||||||
// Line data
|
// Line data
|
||||||
tx_buf = kmemdup(line_data, len, GFP_KERNEL);
|
panel->spi_3_xfers[1].tx_buf = line_data;
|
||||||
tr[1].tx_buf = tx_buf;
|
panel->spi_3_xfers[1].len = len;
|
||||||
tr[1].len = len;
|
|
||||||
|
|
||||||
// Trailer
|
// Trailer
|
||||||
tr[2].tx_buf = trailer_buf;
|
panel->trailer_buf[0] = 0;
|
||||||
tr[2].len = 1;
|
panel->spi_3_xfers[2].tx_buf = panel->trailer_buf;
|
||||||
|
panel->spi_3_xfers[2].len = 1;
|
||||||
|
|
||||||
ndelay(80);
|
ndelay(80);
|
||||||
gpio_set_value(GPIO_SCS, 1);
|
gpio_set_value(GPIO_SCS, 1);
|
||||||
ret = spi_sync_transfer(panel->spi, tr, 3);
|
rc = spi_sync_transfer(panel->spi, panel->spi_3_xfers, 3);
|
||||||
gpio_set_value(GPIO_SCS, 0);
|
gpio_set_value(GPIO_SCS, 0);
|
||||||
|
|
||||||
goto out_free;
|
return rc;
|
||||||
|
|
||||||
out_free:
|
|
||||||
kfree(trailer_buf);
|
|
||||||
kfree(tx_buf);
|
|
||||||
kfree(command_buf);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t sharp_memory_gray8_to_mono_tagged(u8 *buf, int width, int height, int y0)
|
static size_t sharp_memory_gray8_to_mono_tagged(u8 *buf, int width, int height, int y0)
|
||||||
@ -189,8 +173,9 @@ static size_t sharp_memory_gray8_to_mono_tagged(u8 *buf, int width, int height,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use DMA to get grayscale representation, then convert to mono
|
// Use DMA to get grayscale representation, then convert to mono
|
||||||
|
// with line number and trailer tags suitable for multi-line write
|
||||||
// Output is stored in `buf`, which must be at least W*H bytes
|
// Output is stored in `buf`, which must be at least W*H bytes
|
||||||
static int sharp_memory_clip_mono(size_t* result_len, u8* buf,
|
static int sharp_memory_clip_mono_tagged(size_t* result_len, u8* buf,
|
||||||
struct drm_framebuffer *fb, struct drm_rect const* clip)
|
struct drm_framebuffer *fb, struct drm_rect const* clip)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -231,8 +216,6 @@ static int sharp_memory_fb_dirty(struct drm_framebuffer *fb,
|
|||||||
struct sharp_memory_panel *panel;
|
struct sharp_memory_panel *panel;
|
||||||
int drm_idx;
|
int drm_idx;
|
||||||
size_t buf_len;
|
size_t buf_len;
|
||||||
u8 *line;
|
|
||||||
int y;
|
|
||||||
|
|
||||||
// Clip dirty region rows
|
// Clip dirty region rows
|
||||||
clip.x1 = 0;
|
clip.x1 = 0;
|
||||||
@ -248,21 +231,14 @@ static int sharp_memory_fb_dirty(struct drm_framebuffer *fb,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mono contents of `clip` with line number tags
|
// Convert `clip` from framebuffer to mono with line number tags
|
||||||
rc = sharp_memory_clip_mono(&buf_len, panel->buf, fb, &clip);
|
rc = sharp_memory_clip_mono_tagged(&buf_len, panel->buf, fb, &clip);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
goto out_exit;
|
goto out_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write mono data to display
|
// Write mono data to display
|
||||||
line = panel->buf;
|
rc = sharp_memory_spi_write_tagged_lines(panel, panel->buf, buf_len);
|
||||||
for (y = clip.y1; y < clip.y2; y++) {
|
|
||||||
sharp_memory_spi_write_tagged_line(panel, line, fb->width / 8 + 2);
|
|
||||||
line += 2 + (fb->width / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
out_exit:
|
out_exit:
|
||||||
// Exit DRM device resource area
|
// Exit DRM device resource area
|
||||||
@ -434,7 +410,7 @@ static int sharp_memory_probe(struct spi_device *spi)
|
|||||||
// Get DRM device from SPI struct
|
// Get DRM device from SPI struct
|
||||||
dev = &spi->dev;
|
dev = &spi->dev;
|
||||||
|
|
||||||
/* The SPI device is used to allocate dma memory */
|
// The SPI device is used to allocate DMA memory
|
||||||
if (!dev->coherent_dma_mask) {
|
if (!dev->coherent_dma_mask) {
|
||||||
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -443,6 +419,7 @@ static int sharp_memory_probe(struct spi_device *spi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate panel storage
|
||||||
panel = devm_drm_dev_alloc(dev, &sharp_memory_driver,
|
panel = devm_drm_dev_alloc(dev, &sharp_memory_driver,
|
||||||
struct sharp_memory_panel, drm);
|
struct sharp_memory_panel, drm);
|
||||||
if (IS_ERR(panel)) {
|
if (IS_ERR(panel)) {
|
||||||
@ -450,27 +427,34 @@ static int sharp_memory_probe(struct spi_device *spi)
|
|||||||
return PTR_ERR(panel);
|
return PTR_ERR(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initalize DRM mode
|
||||||
drm = &panel->drm;
|
drm = &panel->drm;
|
||||||
|
|
||||||
ret = drmm_mode_config_init(drm);
|
ret = drmm_mode_config_init(drm);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
drm->mode_config.funcs = &sharp_memory_mode_config_funcs;
|
drm->mode_config.funcs = &sharp_memory_mode_config_funcs;
|
||||||
|
|
||||||
|
// Initialize panel contents
|
||||||
panel->spi = spi;
|
panel->spi = spi;
|
||||||
|
|
||||||
mode = &sharp_memory_ls027b7dh01_mode;
|
mode = &sharp_memory_ls027b7dh01_mode;
|
||||||
panel->mode = mode;
|
panel->mode = mode;
|
||||||
panel->width = mode->hdisplay;
|
panel->width = mode->hdisplay;
|
||||||
panel->height = mode->vdisplay;
|
panel->height = mode->vdisplay;
|
||||||
panel->buf = devm_kzalloc(dev, panel->width * panel->height, GFP_KERNEL);
|
|
||||||
|
|
||||||
|
// Allocate reused heap buffers suitable for SPI source
|
||||||
|
panel->buf = devm_kzalloc(dev, panel->width * panel->height, GFP_KERNEL);
|
||||||
|
panel->spi_3_xfers = devm_kzalloc(dev, sizeof(struct spi_transfer) * 3, GFP_KERNEL);
|
||||||
|
panel->cmd_buf = devm_kzalloc(dev, 1, GFP_KERNEL);
|
||||||
|
panel->trailer_buf = devm_kzalloc(dev, 1, GFP_KERNEL);
|
||||||
|
|
||||||
|
// DRM mode settings
|
||||||
drm->mode_config.min_width = mode->hdisplay;
|
drm->mode_config.min_width = mode->hdisplay;
|
||||||
drm->mode_config.max_width = mode->hdisplay;
|
drm->mode_config.max_width = mode->hdisplay;
|
||||||
drm->mode_config.min_height = mode->vdisplay;
|
drm->mode_config.min_height = mode->vdisplay;
|
||||||
drm->mode_config.max_height = mode->vdisplay;
|
drm->mode_config.max_height = mode->vdisplay;
|
||||||
|
|
||||||
|
// Configure DRM connector
|
||||||
drm_connector_helper_add(&panel->connector, &sharp_memory_connector_hfuncs);
|
drm_connector_helper_add(&panel->connector, &sharp_memory_connector_hfuncs);
|
||||||
ret = drm_connector_init(drm, &panel->connector, &sharp_memory_connector_funcs,
|
ret = drm_connector_init(drm, &panel->connector, &sharp_memory_connector_funcs,
|
||||||
DRM_MODE_CONNECTOR_SPI);
|
DRM_MODE_CONNECTOR_SPI);
|
||||||
@ -478,6 +462,7 @@ static int sharp_memory_probe(struct spi_device *spi)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize DRM pipe
|
||||||
ret = drm_simple_display_pipe_init(drm, &panel->pipe, &sharp_memory_pipe_funcs,
|
ret = drm_simple_display_pipe_init(drm, &panel->pipe, &sharp_memory_pipe_funcs,
|
||||||
sharp_memory_formats, ARRAY_SIZE(sharp_memory_formats),
|
sharp_memory_formats, ARRAY_SIZE(sharp_memory_formats),
|
||||||
NULL, &panel->connector);
|
NULL, &panel->connector);
|
||||||
@ -488,12 +473,12 @@ static int sharp_memory_probe(struct spi_device *spi)
|
|||||||
drm_mode_config_reset(drm);
|
drm_mode_config_reset(drm);
|
||||||
|
|
||||||
printk(KERN_INFO "sharp_memory: registering DRM device\n");
|
printk(KERN_INFO "sharp_memory: registering DRM device\n");
|
||||||
|
|
||||||
ret = drm_dev_register(drm, 0);
|
ret = drm_dev_register(drm, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fbdev setup
|
||||||
spi_set_drvdata(spi, drm);
|
spi_set_drvdata(spi, drm);
|
||||||
drm_fbdev_generic_setup(drm, 0);
|
drm_fbdev_generic_setup(drm, 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user