aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2013-04-22 06:02:25 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-05-28 07:41:58 -0400
commit301bc0675b677a98475187050d56cd2b39ff0acf (patch)
tree9e2ab6c8938601fbde69a0a80186a0928979a193 /drivers/video
parent3394e645a88c722396fc1b03c31a3ffc158744ad (diff)
video: ssd1307fb: Make use of horizontal addressing mode
By default, the ssd1307 controller uses an addressing mode called page addressing. This mode only increments the column cursor in memory when writing data but will not increments the page cursor when we are at the end of the page. However, the controller supports another addressing mode, called horizontal addressing, that will maintain both the page and column cursors when writing data to the controller. That means that we can just remove the code that increments the current page address and reset the column cursor when reaching the end of the line, allowing to have a lower data overhead, and a simpler driver. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/ssd1307fb.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
index 04a435886855..44967c8fef2b 100644
--- a/drivers/video/ssd1307fb.c
+++ b/drivers/video/ssd1307fb.c
@@ -19,6 +19,12 @@
19#define SSD1307FB_DATA 0x40 19#define SSD1307FB_DATA 0x40
20#define SSD1307FB_COMMAND 0x80 20#define SSD1307FB_COMMAND 0x80
21 21
22#define SSD1307FB_SET_ADDRESS_MODE 0x20
23#define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL (0x00)
24#define SSD1307FB_SET_ADDRESS_MODE_VERTICAL (0x01)
25#define SSD1307FB_SET_ADDRESS_MODE_PAGE (0x02)
26#define SSD1307FB_SET_COL_RANGE 0x21
27#define SSD1307FB_SET_PAGE_RANGE 0x22
22#define SSD1307FB_CONTRAST 0x81 28#define SSD1307FB_CONTRAST 0x81
23#define SSD1307FB_CHARGE_PUMP 0x8d 29#define SSD1307FB_CHARGE_PUMP 0x8d
24#define SSD1307FB_SEG_REMAP_ON 0xa1 30#define SSD1307FB_SEG_REMAP_ON 0xa1
@@ -135,9 +141,15 @@ static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
135 141
136static void ssd1307fb_update_display(struct ssd1307fb_par *par) 142static void ssd1307fb_update_display(struct ssd1307fb_par *par)
137{ 143{
144 struct ssd1307fb_array *array;
138 u8 *vmem = par->info->screen_base; 145 u8 *vmem = par->info->screen_base;
139 int i, j, k; 146 int i, j, k;
140 147
148 array = ssd1307fb_alloc_array(par->width * par->height / 8,
149 SSD1307FB_DATA);
150 if (!array)
151 return;
152
141 /* 153 /*
142 * The screen is divided in pages, each having a height of 8 154 * The screen is divided in pages, each having a height of 8
143 * pixels, and the width of the screen. When sending a byte of 155 * pixels, and the width of the screen. When sending a byte of
@@ -168,29 +180,22 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
168 */ 180 */
169 181
170 for (i = 0; i < (par->height / 8); i++) { 182 for (i = 0; i < (par->height / 8); i++) {
171 struct ssd1307fb_array *array;
172 ssd1307fb_write_cmd(par->client,
173 SSD1307FB_START_PAGE_ADDRESS + i + par->page_offset);
174 ssd1307fb_write_cmd(par->client, 0x00);
175 ssd1307fb_write_cmd(par->client, 0x10);
176
177 array = ssd1307fb_alloc_array(par->width, SSD1307FB_DATA);
178
179 for (j = 0; j < par->width; j++) { 183 for (j = 0; j < par->width; j++) {
180 array->data[j] = 0; 184 u32 array_idx = i * par->width + j;
185 array->data[array_idx] = 0;
181 for (k = 0; k < 8; k++) { 186 for (k = 0; k < 8; k++) {
182 u32 page_length = par->width * i; 187 u32 page_length = par->width * i;
183 u32 index = page_length + (par->width * k + j) / 8; 188 u32 index = page_length + (par->width * k + j) / 8;
184 u8 byte = *(vmem + index); 189 u8 byte = *(vmem + index);
185 u8 bit = byte & (1 << (j % 8)); 190 u8 bit = byte & (1 << (j % 8));
186 bit = bit >> (j % 8); 191 bit = bit >> (j % 8);
187 array->data[j] |= bit << k; 192 array->data[array_idx] |= bit << k;
188 } 193 }
189 } 194 }
190
191 ssd1307fb_write_array(par->client, array, par->width);
192 kfree(array);
193 } 195 }
196
197 ssd1307fb_write_array(par->client, array, par->width * par->height / 8);
198 kfree(array);
194} 199}
195 200
196 201
@@ -371,6 +376,26 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
371 if (ret < 0) 376 if (ret < 0)
372 return ret; 377 return ret;
373 378
379 /* Switch to horizontal addressing mode */
380 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
381 ret = ret & ssd1307fb_write_cmd(par->client,
382 SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
383 if (ret < 0)
384 return ret;
385
386 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
387 ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
388 ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
389 if (ret < 0)
390 return ret;
391
392 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
393 ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
394 ret = ret & ssd1307fb_write_cmd(par->client,
395 par->page_offset + (par->height / 8) - 1);
396 if (ret < 0)
397 return ret;
398
374 /* Turn on the display */ 399 /* Turn on the display */
375 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); 400 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
376 if (ret < 0) 401 if (ret < 0)