Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Maxime Ripard and committed by
Tomi Valkeinen
301bc067 3394e645

+38 -13
+38 -13
drivers/video/ssd1307fb.c
··· 19 19 #define SSD1307FB_DATA 0x40 20 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 28 #define SSD1307FB_CONTRAST 0x81 23 29 #define SSD1307FB_CHARGE_PUMP 0x8d 24 30 #define SSD1307FB_SEG_REMAP_ON 0xa1 ··· 141 135 142 136 static void ssd1307fb_update_display(struct ssd1307fb_par *par) 143 137 { 138 + struct ssd1307fb_array *array; 144 139 u8 *vmem = par->info->screen_base; 145 140 int i, j, k; 141 + 142 + array = ssd1307fb_alloc_array(par->width * par->height / 8, 143 + SSD1307FB_DATA); 144 + if (!array) 145 + return; 146 146 147 147 /* 148 148 * The screen is divided in pages, each having a height of 8 ··· 180 168 */ 181 169 182 170 for (i = 0; i < (par->height / 8); i++) { 183 - struct ssd1307fb_array *array; 184 - ssd1307fb_write_cmd(par->client, 185 - SSD1307FB_START_PAGE_ADDRESS + i + par->page_offset); 186 - ssd1307fb_write_cmd(par->client, 0x00); 187 - ssd1307fb_write_cmd(par->client, 0x10); 188 - 189 - array = ssd1307fb_alloc_array(par->width, SSD1307FB_DATA); 190 - 191 171 for (j = 0; j < par->width; j++) { 192 - array->data[j] = 0; 172 + u32 array_idx = i * par->width + j; 173 + array->data[array_idx] = 0; 193 174 for (k = 0; k < 8; k++) { 194 175 u32 page_length = par->width * i; 195 176 u32 index = page_length + (par->width * k + j) / 8; 196 177 u8 byte = *(vmem + index); 197 178 u8 bit = byte & (1 << (j % 8)); 198 179 bit = bit >> (j % 8); 199 - array->data[j] |= bit << k; 180 + array->data[array_idx] |= bit << k; 200 181 } 201 182 } 202 - 203 - ssd1307fb_write_array(par->client, array, par->width); 204 - kfree(array); 205 183 } 184 + 185 + ssd1307fb_write_array(par->client, array, par->width * par->height / 8); 186 + kfree(array); 206 187 } 207 188 208 189 ··· 373 368 /* Turn on the DC-DC Charge Pump */ 374 369 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP); 375 370 ret = ret & ssd1307fb_write_cmd(par->client, 0x14); 371 + if (ret < 0) 372 + return ret; 373 + 374 + /* Switch to horizontal addressing mode */ 375 + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE); 376 + ret = ret & ssd1307fb_write_cmd(par->client, 377 + SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL); 378 + if (ret < 0) 379 + return ret; 380 + 381 + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE); 382 + ret = ret & ssd1307fb_write_cmd(par->client, 0x0); 383 + ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1); 384 + if (ret < 0) 385 + return ret; 386 + 387 + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE); 388 + ret = ret & ssd1307fb_write_cmd(par->client, 0x0); 389 + ret = ret & ssd1307fb_write_cmd(par->client, 390 + par->page_offset + (par->height / 8) - 1); 376 391 if (ret < 0) 377 392 return ret; 378 393