This comes from IRC disscusion with Jens Arnold - the author of greylib

For this purpose there are two test plugins you need to build: test_scanrate and test_grey test_scanrate in turn needs a working lcd_blit_mono().

First, you run test_scanrate and increase/decrease the frequency until the black blob at the left stops, or nearly stops. Note down the frequency, then create an #elif section at the top of grey_core.c for your lcd. Change the #define LCD_SCANRATE to the nearest HZ value of frequency you measured.

Then rebuild the plugins, so test_grey will use the new value. If you run test_grey, you'll see 9 rectangles in a black frame. With left/right you can change the grey level you're adjusting, with up/down you change the value. The outer 8 rectangles use ordinary ordered dither to approximate a level of grey, only the central one uses the actual greylib mechanism. The goal is to adjust the center rectangle (with up/down) to match the brightness of the left, right, top and bottom rectangles at each of the levels. In order to do this, watch the display in a not too bright environment, keep it away far enough so the dithering works (arm's length) and try looking exactly perpendicular (as contrast varies with angle). When finished, exit the plugin. It will write a result file to the root. This result file can then be used to create the lcdlinear[] array by using interpolation. This step isn't automated yet..... sorry

EDIT: As of r26869 output from test_grey contains interpolated dump which can be almost 'just as is' copied as lcdlinear[].